Jump to content

Modding:Migrate to Stardew Valley 1.7: Difference between revisions

From Stardew Valley Wiki
imported>Pathoschild
imported>Blueberry
 
(129 intermediate revisions by 4 users not shown)
Line 2: Line 2:


{{Modder compatibility header}}
{{Modder compatibility header}}
{{upcoming|1.6.16|message='''⚠ No upcoming Stardew Valley update has been announced.'''<br />This page describes changes accumulated in the game's pre-alpha development branch. There's no estimated release date or even assigned version number for these changes yet. Things ''will'' change before it's released!}}
{{upcoming|1.7|message='''⚠ [https://x.com/ConcernedApe/status/1961864959484412104 Stardew Valley 1.7 was announced], but has no planned release date.'''<br />There's no estimate for when the update will be released, so don't plan mod updates around the 1.7 release. Things ''will'' change before it's released!}}


This page helps mod authors prepare their mods for the next game version (tentatively {{version|1.6.16|Stardew Valley 1.6.16}}), and documents some of the changes and new functionality.
This page helps mod authors prepare their mods for the upcoming <!--{{version|1.7|Stardew Valley 1.7}}-->Stardew Valley 1.7, and documents some of the changes and new functionality.


{{TOC|limit=3}}
{{TOC|limit=3}}
Line 12: Line 12:


===What's changing?===
===What's changing?===
Stardew Valley 1.6.16 makes [[#Event changes|significant changes to event data]], but otherwise so far only has small changes for mods following the major 1.6 and 1.6.9 updates.
Stardew Valley 1.7 makes significant changes to many data assets to enable new game features and mod extensibility. See the sections below for more details.


===Is this the modapocalypse?===
===Is this the modapocalypse?===
No, the current impact on mods is expected to be minimal.
Probably not. SMAPI and Content Patcher will automatically rewrite older mods for many of the changes, so they should still work as-is. Some mods may need an update.
 
Some potential impacts:
* The [[#Event changes|event changes]] may affect mods which edit vanilla events or add pre-1.6 events with numeric IDs. Content packs for [[Modding:Content Patcher|Content Patcher]] should be mostly unaffected, since it will rewrite older content packs automatically where possible.
* Mods which use Harmony or reflection to hook deeply into game internals are fragile, and may break unexpectedly in any game update. However there are no particular changes in 1.6.16 expected to affect such mods more than usual.


===How to update your mod===
===How to update your mod===
Here's a suggested 'quick start' guide to update a mod for Stardew Valley 1.6.16.
Here's a suggested 'quick start' guide to update a mod for Stardew Valley 1.7.


; For C# mods&#58;
; For C# mods&#58;
:# [[Modding:Migrate to Stardew Valley 1.6.9#How to update your mod|Update for Stardew Valley 1.6.9]] if you haven't already.
:# [[Modding:Migrate to Stardew Valley 1.6.16#How to update your mod|Update for Stardew Valley 1.6.16]] if you haven't already.
:# Rebuild the solution.
:# Rebuild the solution.
:# Fix any build errors and review any build warnings. You can search this page and [[Modding:Index#Migration guides|previous migration guides]] for relevant info as needed.
:# Fix any build errors and review any build warnings. You can search this page and [[Modding:Index#Migration guides|previous migration guides]] for relevant info as needed.
Line 33: Line 29:


; For [[Modding:Content Patcher|Content Patcher]] packs&#58;
; For [[Modding:Content Patcher|Content Patcher]] packs&#58;
:# [[Modding:Migrate to Stardew Valley 1.6.9#How to update your mod|Update for Stardew Valley 1.6.9]] if you haven't already.
:# [[Modding:Migrate to Stardew Valley 1.6.16#How to update your mod|Update for Stardew Valley 1.6.16]] if you haven't already.
:# Skim through this page, and check any section that might be relevant to the mod.
:# Skim through this page, and check any section that might be relevant to the mod.


Line 88: Line 84:
|}
|}


For example, here's how to add new boots in 1.6.16:
For example, here's how to add new boots in 1.7:
{{Content Patcher example|<nowiki>
{{Content Patcher example|<nowiki>
     "Changes": [
     "Changes": [
Line 117: Line 113:


===[[Modding:Buffs|<samp>Data/Buffs</samp>]]===
===[[Modding:Buffs|<samp>Data/Buffs</samp>]]===
Added one new field:
Added one new field to buff attributes, contained in the <samp>Effects</samp> field:


{| class="wikitable"
{| class="wikitable"
Line 128: Line 124:
|}
|}


===[[Modding:Maps#Sitting on non-furniture chairs|<samp>Data/ChairTiles</samp>]]===
===[[Modding:Objects|<samp>Data/Characters</samp>]]===
* Fixed support for tilesheet asset names containing a dot. (For example, a tileseet asset named <code>ExampleAuthor.ModName_Tilesheet</code> now correctly uses that as the data key instead of <code>ExampleAuthor</code>.)
The following fields have been added:


===[[Modding:Recipe data|<samp>Data/CookingRecipes</samp>]]===
{| class="wikitable"
These cooking recipe keys were changed to match their object name (like all the other recipes):
|-
! field
! effect
|-
| <samp>FlowerDanceBehavior</samp>
| ''(Optional)'' A list of behaviors to consider for use during the Flower Festival. If no matching ones are found, the default behavior for that NPC's gender is used.


Each entry in this list has the following fields:
{| class="wikitable"
{| class="wikitable"
|-
|-
! old name
! field
! new name
! effect
|-
|-
| Cheese Cauli.
| <samp>Id</samp>
| Cheese Cauliflower
| An ID for this entry within the dance behavior list. This only needs to be unique within the current list.
|-
|-
| Cookies
| <samp>Condition</samp>
| Cookie
| A game state query which indicates whether this entry is a valid choice. Default true.
|-
|-
| Cran. Sauce
| <samp>Sprite</samp>
| Cranberry Sauce
| The sprite to use for the dance, as would be passed in to the <samp>changeSprite</samp> event command. Default null.
|-
|-
| Dish o' The Sea
| <samp>FirstDanceFrame</samp>
| Dish O' The Sea
| The first frame of the relevant spritesheet to use for the dance animation.
 
The animation frames after this index must still follow the standard structure.
|-
|-
| Eggplant Parm.
| <samp>Precedence</samp>
| Eggplant Parmesan
| The order in which this behavior should be checked, where 0 is the default value used by most behaviors.
|-
|}
| Vegetable Stew
| Vegetable Medley
|}
|}


This has no effect on the display text, but mods which reference these recipe keys will need to be updated.
===<samp>Data/CraftingRecipes</samp> and <samp>Data/CookingRecipes</samp>===
 
Crafting recipes and cooking recipes are now a data model. The data model for both are identical. Crafting recipes still live in <samp>Data/CraftingRecipes</samp>, and cooking recipes still live in <samp>Data/CookingRecipes</samp>.
===[[Modding:Event data|<samp>Data/Events/*</samp>]]===
See ''[[#Event changes|event changes]]'' below.
 
===[[Modding:Furniture|<samp>Data/Furniture</samp>]]===
This has been overhauled into a data model asset. The overhaul also adds support for previously-hardcoded features like custom item descriptions (via <samp>Description</samp>), custom TVs (via the new <samp>Television</samp> furniture type and <samp>TelevisionScreen*</samp> fields), and [[Modding:Common data field types#Custom fields|custom fields]].
 
The data asset now consists of a string → model lookup, where...
* The key is the [[Modding:Common data field types#Item ID|unqualified item ID]].
* The value is a model with the fields listed below.


Both assets are dictionary assets. The key is the recipe ID, the same as in 1.6, and the value is a data model with the following fields:
{| class="wikitable"
{| class="wikitable"
|-
|-
! field
! field
! effect
! effect
|-
!colspan="2"| basic info
|-
| <samp>Name</samp>
| The internal item name (not shown in-game).
|-
|-
| <samp>DisplayName</samp>
| <samp>DisplayName</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name.
| A [[Modding:Tokenizable strings|tokenizable string]] for the display name of this recipe.
|-
|-
| <samp>Description</samp>
| <samp>Description</samp>
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game description. Defaults to a generic description based on the other fields like <samp>CanPlaceIndoors</samp> and <samp>CanPlaceOutdoors</samp>.
| A [[Modding:Tokenizable strings|tokenizable string]] for the description of this recipe.
|-
|-
| <samp>Type</samp>
| <samp>Ingredients</samp>
| ''(Optional)'' The furniture type, which affects various furniture functionality and default values (e.g. default bounding box size). Defaults to <samp>Other</samp>.
| A list of ingredients for this recipe.
{| class="wikitable"
|-
! field
! effect
|-
| <samp>Id</samp>
| TThe [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry (not the item itself) within the current list.


See [[Modding:Furniture#Furniture types|table of valid types]].
This is semi-optional — if omitted, it'll be auto-generated from <samp>ItemId</samp>. However multiple entries with the same ID may cause unintended behavior, so it's often a good idea to set a globally unique ID instead.
|-
|-
| <samp>Price</samp>
| <samp>ItemId</samp>
| ''(Optional)'' The price for this furniture when purchased from a shop. Default 0.
| The item for this ingredient. This can be either a qualified item ID, or a context tag.
 
If a context tag is specified, it needs to have a corresponding entry in <samp>[[#Context tag changes|Data/ContextTags]]</samp>.
|-
|-
| <samp>ContextTags</samp>
| <samp>Quantity</samp>
| ''(Optional)'' The custom [[Modding:Context tags|context tags]] to add for this item (in addition to the tags added automatically based on the other item data), specified as an array.
| The amount of this ingredient to require. Default 1.
|-
|-
!colspan="2"| behavior
| <samp>Condition</samp>
| The [[Modding:Game state queries|game state query]] for this ingredient. If not specified, defaults to TRUE.
|-
|-
| <samp>CanPlaceIndoors</samp><br /><samp>CanPlaceOutdoors</samp>
| <samp>CustomFields</samp>
| ''(Optional)'' Whether the player can place this furniture indoors and/or outdoors. Defaults to generic behavior based on the <samp>Type</samp> field (e.g. TVs can't be placed outdoors by default).
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
|}
|-
|-
| <samp>ExcludeFromRandomSale</samp>
| <samp>Result</samp>
| ''(Optional)'' Whether to prevent this furniture from being shown in randomly generated shop stock or furniture catalogues. Default false.
| The possible results for this recipe. This is a list of [[Modding:Item queries#Item spawn fields|conditional item spawn fields]].
 
If there are multiple resulting possibilities at once, the one chosen for display in menus uses the following precedence:
# First, it checks the recipe's <samp>DisplayItemId</samp>.
# If there was no <samp>DisplayItemId</samp>, then it will search all results for the first one that is not conditional (eg. <samp>Condition</samp> is either <samp>null</samp> or <samp>TRUE</samp>).
# If no unconditional results were found, then it chooses the first result, regardless of if the condition passes.
|-
|-
!colspan="2"| appearance
| <samp>DisplayItemId</samp>
| A qualified item ID to override the displayed item in menus.
|-
|-
| <samp>Texture</samp>
| <samp>Unlock</samp>
| The [[Modding:Common data field types#Asset name|asset name]] for the texture containing the furniture sprite. Defaults to <samp>TileSheets/furniture</samp> if omitted, but should always be specified for custom furniture.
| The unlock conditions for this recipe.
{| class="wikitable"
|-
|-
| <samp>SpriteIndex</samp>
! field
| ''(Optional)'' The sprite's index within the <samp>Texture</samp>, where 0 is the top-left sprite. Default 0.
! effect
|-
|-
| <samp>Rotations</samp>
| <samp>Trigger</samp>
| ''(Optional)'' The number of rotations possible (1, 2, or 4). Default 1.
|  
{| class="wikitable"
|-
|-
| <samp>SpriteSize</samp>
! name
| ''(Optional)'' The sprite's size in the <samp>Texture</samp>, measured in tiles. Defaults to a generic size depending on the <samp>Type</samp> field.
! effect
|-
|-
| <samp>BoundingBoxSize</samp>
| <samp>DayStart</samp>
| ''(Optional)'' The collision box size when the furniture is placed in-game, measured in tiles. Defaults to a generic size depending on the <samp>Type</samp> field.
| Checks the <samp>Condition</samp> at the beginning of each day.
 
The bounding box is anchored to the bottom-left corner of the <samp>SpriteSize</samp>. Width will push the right side of the box to the right, height will push the top of the box upwards.
|-
|-
!colspan="2"| type-specific options
| <samp>Mail</samp>
| Checks the <samp>Condition</samp> at the beginning of each day, and queues <samp>MailLetterName</samp> for the mailbox if the condition passed.
|-
|-
| <samp>BedType</samp>
| <samp>LevelUp</samp>
| ''(Optional)'' When the <samp>Type</samp> field is set to <samp>Bed</samp>, the bed type which affects who can sleep in it. Default <samp>Single</samp>.
| Appears when reaching a level <samp>RequiredSkillLevel</samp> in the <samp>RequiredSkill</samp> skill. <samp>Condition</samp> is ignored.
 
Valid values:
{| class="wikitable"
|-
|-
! bed type
| <samp>Default</samp>
! effect
| Added as a default recipe. <samp>Condition</samp> is ignored.
|}
|-
|-
| <samp>Single</samp>
| <samp>Condition</samp>
| A single-sized bed with room for one player or NPC.
| The [[Modding:Game state queries|game state query]] for this unlock. If not specified, defaults to TRUE.
|-
|-
| <samp>Double</samp>
| <samp>RequiredSkill</samp>
| A double-sized bed with room for two players or NPCs.
| The skill for the required level for this unlock, if <samp>Trigger</samp> is equal to <samp>LevelUp</samp>.
|-
|-
| <samp>Child</samp>
| <samp>RequiredSkillLevel</samp>
| A single bed for a child NPC.
| The required level for this unlock, if <samp>Trigger</samp> is equal to <samp>LevelUp</samp>.
|}
|-
|-
| <samp>TelevisionScreenOffset</samp>
| <samp>MailLetterName</samp>
| ''(Optional)'' When the <samp>Type</samp> field is set to <samp>Television</samp>, the X and Y pixel offset relative to the TV's bounding box to apply when drawing the screen image onto the TV. Default none.
| The name of letter sent for unlock, if <samp>Trigger</samp> is equal to <samp>Mail</samp>.
|-
|-
| <samp>TelevisionScreenScale</samp>
| <samp>CustomFields</samp>
| ''(Optional)'' When the <samp>Type</samp> field is set to <samp>Television</samp>, the zoom multiplier to apply to the screen image so it fits onto the TV's screen.
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
|}
|-
|-
!colspan="2"| advanced
| <samp>ExcludeFromPerfection</samp>
| Whether or not to exclude this recipe from perfection checks. Default false.
|-
|-
| <samp>CustomFields</samp>
| <samp>CustomFields</samp>
Line 257: Line 263:
|}
|}


===[[Modding:Hats|<samp>Data/Hats</samp>]]===
===[[Modding:Gift taste data|<samp>Data/GiftTastes</samp>]]===
This has been overhauled into a data model asset, with translations moved into a new <samp>Strings/Hats</samp> asset. This also includes new fields like <samp>ContextTags</samp> and <samp>CustomFields</samp> which weren't available in the old format.
Gift tastes, previously in <samp>Data/NPCGiftTastes</samp> with a localized version for every language, are now in <samp>Data/GiftTastes</samp> (taste data only) and <samp>Strings/GiftTasteReactions</samp> (reaction strings, one per language).
 
Responses to gifts are pulled from <samp>Strings/GiftTasteReactions</samp>, with the entry chosen from the following format: <samp>{NPC}_{Taste}</samp>, with <samp>{NPC}</samp> being the NPC ID, and <samp>{Taste}</samp> being the corresponding taste (ex. <samp>Penny_Love</samp> for Penny's loved gift response).
 
For the gift taste data itself, it now works based on a precedence and [[Modding:Game state queries | game state query]] system. Additionally, a gift taste can apply to multiple NPCs at once.


The data asset now consists of a string → model lookup, where...
<samp>Data/GiftTastes</samp> is a list of gift taste entries, with the following format:
* The key is the [[Modding:Common data field types#Item ID|unqualified item ID]].
* The value is a model with the fields listed below.


{| class="wikitable"
{| class="wikitable"
Line 269: Line 277:
! effect
! effect
|-
|-
!colspan="2"| basic info
| <samp>Id</samp>
| The ID of this entry.
|-
| <samp>Condition</samp>
| ''(Optional)'' The [[Modding:Game state queries | game state query]] for if this gift taste should apply, if any.
|-
|-
| <samp>Name</samp>
| <samp>Precedence</samp>
| The internal item name (not shown in-game).
| ''(Optional, but recommended)'' The precedence for this entry, with higher values being checked first.
 
For the precedence decided for various base game's gift tastes, see the notes after this table.
|-
|-
| <samp>DisplayName</samp><br /><samp>Description</samp>
| <samp>ItemId</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name and description.
| The item that matches this gift taste. This can be a qualified item ID, a category, or a [[Modding:Context tags | context tag]] query.
|-
|-
| <samp>HairStyle</samp>
| <samp>Taste</samp>
| ''(Optional)'' What to do about the player's hair when they wear this hat. Default <samp>DrawObscuredHair</samp>.
| The gift taste that applies for this entry. Possible values are <samp>Love</samp>, <samp>Like</samp>, <samp>Neutral</samp>, <samp>Dislike</samp>, and <samp>Hate</samp>.
|-
| <samp>AppliesTo</samp>
| ''(Optional)'' Who this gift taste applies to. This is a comma-separated list of NPC names.


The possible values are:
If not specified, applies to all NPCs.
* <samp>DrawFullHair</samp>: the hair is drawn like usual (e.g. for hats that don't hide the hair like [[Abigail's Bow|Abigail's bow]]).
* <samp>DrawObscuredHair</samp>: the hair is partly obscured under the hat (e.g. for most hats like the [[Cowboy Hat|cowboy hat]]).
* <samp>HideHair</samp>: the hair is fully hidden (e.g. for hats which fully cover the head like the [[Mummy Mask|mummy mask]]).
|-
|-
| <samp>SkipHairOffset</samp>
!colspan="2"| advanced
| ''(Optional)'' Whether to skip offsetting the hat to sit 'on top' of the player's current hairstyle (e.g. for masks). Default false.
|-
| <samp>Texture</samp>
| The [[Modding:Common data field types#Asset name|asset name]] for the texture containing the hat sprite. Defaults to <samp>Characters/Farmer/hats</samp> if omitted, but should always be specified for custom hats.
|-
| <samp>SpriteIndex</samp>
| ''(Optional)'' The sprite's index within the <samp>Texture</samp>, where 0 is the top-left sprite. Default 0.
|-
| <samp>ContextTags</samp>
| ''(Optional)'' The custom [[Modding:Context tags|context tags]] to add for this item (in addition to the tags added automatically based on the other item data), specified as an array.
|-
|-
| <samp>CustomFields</samp>
| <samp>CustomFields</samp>
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
|}
|}


For example, here's how to add a new hat in 1.6.16:
==== Precedences for old gift taste data ====
{{Content Patcher example|<nowiki>
When converting the base game's legacy gift taste data, the precedence values were determined in a way to match previous behavior.
    "Changes": [
 
        // add data
First, a base precedence was chosen based on who it applied to and what type of match it was:
        {
{| class="wikitable"
            "Action": "EditData",
|-
            "Target": "Data/Hats",
! base precedence
            "Entries": {
! who
                "{{ModId}}_FancyHat": {
! what
                    "Name": "{{ModId}}_FancyHat",
|-
                    "DisplayName": "{{i18n: fancy-hat.name}}",
| 0
                    "Description": "{{i18n: fancy-hat.description}}",
| Specific character
                    "HairStyle": "DrawObscuredHair",
| Specific item
                    "Texture": "Mods/{{ModId}}/Hats",
                    "SpriteIndex": 0
                }
            }
        },
 
        // add texture
        {
            "Action": "Load",
            "Target": "Mods/{{ModId}}/Hats",
            "FromFile": "assets/hats.png"
        }
    ]
</nowiki>}}
 
===[[Modding:Lost items shop|<samp>Data/LostItemsShop</samp>]]===
Added one new field:
{| class="wikitable"
|-
|-
! field
| -1000
! effect
| Specific character
| Items matching a context tag
|-
|-
| <samp>RequireCondition</samp>
| -2000
| ''(Optional)'' The [[Modding:Game state queries|game state queries]] which must match to add this item. The <samp>Target</samp> player is the one being checked.
| Universal
 
| Specific item
This field should generally only be used with deterministic game state queries.
|-
| -3000
| Specific character
| Items of a specific category
|-
| -4000
| Universal
| Items matching a context tag
|-
| -5000
| Universal
| Items of a specific category
|}
|}


If you specify multiple criteria fields, only one is applied in this order: <samp>RequireMailReceived</samp>, then <samp>RequireEventSeen</samp>, then <samp>RequireCondition</samp>.
After the base precedence is selected, an additional value is added based on the resulting gift taste.  
 
===[[Modding:Passive Festival data|<samp>Data/PassiveFestivals</samp>]]===
Added one new field:
{| class="wikitable"
{| class="wikitable"
|-
|-
! field
! precedence modifier
! effect
! legacy gift taste
|-
| 400
| Love
|-
| 300
| Hate
|-
| 200
| Like
|-
| 100
| Dislike
|-
|-
| <samp>InLocations</samp>
| 0
| ''(Optional)'' The locations in which the festival happens. This affects various game logic like NPC dialogues, tent placement restrictions, weather, etc. If omitted, defaults to the keys in <samp>MapReplacements</samp>.
| Neutral
|}
|}


===[[Modding:Monster data|<samp>Data/Monsters</samp>]]===
Additionally, the previously hard-coded behavior of everyone disliking artifacts (except Penny and the Dwarf, who like them) are now in the data, with a precedence of -1250 (universal dislike) and -1200 (Penny and Dwarf like).
Monster data has been completely rethought in Stardew Valley 1.6.16. In particular...
 
* For monster data in general:
Certain fallback behavior for cheap or negative ediblity otherwise-neutral-reaction items are still hardcoded, but still only apply if:
** <samp>Data/Monsters</samp> has been been overhauled into a data model asset, with translations moved into a new <samp>Strings/Monsters</samp> asset. This includes significant new features which weren't supported with the old format.
* the chosen gift taste was neutral
** A new 'monster variant' concept lets multiple specific monsters share common data (e.g. <samp>Green Slime</samp> and <samp>Tiger Slime</samp> are variants of the new base <samp>Slime</samp> monster). This is particularly used for common drops.
* the chosen gift taste applies to everyone (ie. was universal)
** A new 'monster tag' system lets monster define custom tags like <samp>slime_is_prismatic</samp>, which can be used to filter monster drops.
* the chosen gift taste was for that specific item, and not an entire category or context tag
* For monster drops:
 
** A rethought monster drop system supports the full range of vanilla features like [[Modding:Game state queries|conditions]], [[Modding:Item queries|item queries]], [[Modding:Common data field types#Item ID|qualified item IDs]] for non-object drops, and monster-specific concepts like repeating drop chance and mutually-exclusive drops.
===[[Modding:Furniture|<samp>Data/Furniture</samp>]]===
** All drops are now [[Modding:Common data field types#Item ID|qualified item IDs]]. The former 'resource IDs' (formatted as negative numbers like <samp>-4</samp>) are no longer supported; items are converted into their equivalent resource debris automatically where needed.
This has been overhauled into a data model asset. The overhaul also adds support for previously-hardcoded features like custom item descriptions (via <samp>Description</samp>), custom TVs (via the new <samp>Television</samp> furniture type and <samp>TelevisionScreen*</samp> fields), and [[Modding:Common data field types#Custom fields|custom fields]].
** Nearly all monster drops are now defined in <samp>Data/Monsters</samp> (with just a few hardcoded drops common to all monsters left).


The data asset now consists of a string → model lookup, where...
The data asset now consists of a string → model lookup, where...
* The key is the [[Modding:Common data field types#Unique string ID|unique string ID]].
* The key is the [[Modding:Common data field types#Item ID|unqualified item ID]].
* The value is a model with the fields listed below.
* The value is a model with the fields listed below.


Line 376: Line 383:
|-
|-
!colspan="2"| basic info
!colspan="2"| basic info
|-
| <samp>Name</samp>
| The internal item name (not shown in-game).
|-
|-
| <samp>DisplayName</samp>
| <samp>DisplayName</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the monster's display name.
| A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name.
|-
|-
| <samp>IsGlider</samp>
| <samp>Description</samp>
| ''(Optional)'' Whether the monster is flying (e.g. so they glide over obstacles). Default false.
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game description. Defaults to a generic description based on the other fields like <samp>CanPlaceIndoors</samp> and <samp>CanPlaceOutdoors</samp>.
|-
|-
| <samp>IsMineMonster</samp>
| <samp>Type</samp>
| ''(Optional)'' Whether this monster spawns in the mines, and should be buffed after the player reaches the bottom. This sometimes applies to monsters that can appear elsewhere too (e.g. [[Wilderness Golem|wilderness golems]] on the farm receive mine buffs too). Default false.
| ''(Optional)'' The furniture type, which affects various furniture functionality and default values (e.g. default bounding box size). Defaults to <samp>Other</samp>.
 
See [[Modding:Furniture#Furniture types|table of valid types]].
|-
|-
| <samp>ExperiencePoints</samp>
| <samp>Price</samp>
| ''(Optional)'' The combat [[Skills|experience points]] received for defeating the monster. Default 1.
| ''(Optional)'' The price for this furniture when purchased from a shop. Default 0.
|-
|-
!colspan="2"| stats
| <samp>ContextTags</samp>
| ''(Optional)'' The custom [[Modding:Context tags|context tags]] to add for this item (in addition to the tags added automatically based on the other item data), specified as an array.
|-
|-
| <samp>Health</samp>
!colspan="2"| behavior
| ''(Optional)'' The initial hit points. Default 20.
|-
|-
| <samp>Attack</samp>
| <samp>CanPlaceIndoors</samp><br /><samp>CanPlaceOutdoors</samp>
| ''(Optional)'' The attack power (i.e. how much damage its hits inflict on players). Default 5.
| ''(Optional)'' Whether the player can place this furniture indoors and/or outdoors. Defaults to generic behavior based on the <samp>Type</samp> field (e.g. TVs can't be placed outdoors by default).
|-
|-
| <samp>Defense</samp>
| <samp>ExcludeFromRandomSale</samp>
| ''(Optional)'' The defense which reduces damage received by this monster. Default 0.
| ''(Optional)'' Whether to prevent this furniture from being shown in randomly generated shop stock or furniture catalogues. Default false.
|-
|-
| <samp>DodgeChance</samp>
!colspan="2"| appearance
| ''(Optional)'' The percentage chance that the monster dodges an attack, as a value between 0 (never) and 1 (always). Default 0.
|-
|-
| <samp>Speed</samp>
| <samp>Texture</samp>
| ''(Optional)'' The default movement speed. Default 1.
| The [[Modding:Common data field types#Asset name|asset name]] for the texture containing the furniture sprite. Defaults to <samp>TileSheets/furniture</samp> if omitted, but should always be specified for custom furniture.
|-
|-
| <samp>Jitteriness</samp>
| <samp>SpriteIndex</samp>
| ''(Optional)'' How often the monster will move in random non-player directions to try to get around objects, as a value between 0 (never) and 1 (always). Default 0.1.
| ''(Optional)'' The sprite's index within the <samp>Texture</samp>, where 0 is the top-left sprite. Default 0.
|-
|-
| <samp>DetectionDistance</samp>
| <samp>Rotations</samp>
| ''(Optional)'' The distance at which the monster detects a player and begins moving towards them, or -1 for unlimited. Default 4.
| ''(Optional)'' The number of rotations possible (1, 2, or 4). Default 1.
|-
|-
!colspan="2"| drops
| <samp>SpriteSize</samp>
| ''(Optional)'' The sprite's size in the <samp>Texture</samp>, measured in tiles. Defaults to a generic size depending on the <samp>Type</samp> field.
|-
|-
| <samp>Drops</samp>
| <samp>BoundingBoxSize</samp>
| ''(Optional)'' The items which can drop when the monster is defeated. Default none.
| ''(Optional)'' The collision box size when the furniture is placed in-game, measured in tiles. Defaults to a generic size depending on the <samp>Type</samp> field.


All matching entries are dropped. If the player has a [[Burglar's Ring|burglar's ring]] equipped, each entry will make two attempts to drop (but fields like <samp>RepeatingChance</samp> and <samp>SkipIfDropped</samp> are independent between the two attempts).
The bounding box is anchored to the bottom-left corner of the <samp>SpriteSize</samp>. Width will push the right side of the box to the right, height will push the top of the box upwards.
|-
!colspan="2"| type-specific options
|-
| <samp>BedType</samp>
| ''(Optional)'' When the <samp>Type</samp> field is set to <samp>Bed</samp>, the bed type which affects who can sleep in it. Default <samp>Single</samp>.


This consists of a list of models with these fields:
Valid values:
{| class="wikitable"
{| class="wikitable"
|-
|-
! field
! bed type
! effect
! effect
|-
|-
| ''common fields''
| <samp>Single</samp>
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for monster drops.
| A single-sized bed with room for one player or NPC.
 
Notes:
* If a drop has an [[Modding:Item queries|item query]] which returns multiple item stacks, one of them will be selected at random.
* The <samp>Condition</samp> field can optionally contain the <code>%RANDOM_KEY</code> token, which is set to a unique identifier for this monster during the current tick.
|-
|-
| <samp>ForTags</samp>
| <samp>Double</samp>
| ''(Optional)'' The monster tags for which this drop applies. This can be a [[Modding:Context tags|context tag]]-like query string like <samp>!variant_frost_bat, !variant_lava_bat</samp> (not [[Frost Bat|frost bat]] or [[Lava Bat|lava bat]]). Default none, meaning it applies to all monsters with this data.
| A double-sized bed with room for two players or NPCs.
|-
|-
| <samp>Chance</samp>
| <samp>Child</samp>
| ''(Optional)'' A probability that this item will be found, as a value between 0 (never) and 1 (always). Default 1.
| A single bed for a child NPC.
|}
|-
|-
| <samp>RepeatingChance</samp>
| <samp>BedUpgradeItemId</samp>
| ''(Optional)'' A compounding probability of an extra drop, as a value between 0 (never) and .95 (nearly always). Default 0.
| ''(Optional)'' When the <samp>Type</samp> field is set to <samp>Bed</samp>, the item ID of the double bed to replace with for house upgrades. Default <samp>null</samp>.


This applies after an item has been dropped based on the other fields. This chance is repeatedly checked to produce an extra drop until it fails. Each repeat drop will ignore the <samp>Chance</samp> and <samp>Condition</samp> fields, but reapply all other item spawn fields (e.g. re-selecting <samp>RandomItemId</samp> if applicable).
If omitted, when choosing a double bed for an upgraded Farmhouse or Cabin, a legacy integer <samp>ItemId</samp> will result in a value of <samp>ItemId + 4</samp>, otherwise the default value of <samp>2052</samp> will be used.
|-
| <samp>TelevisionScreenOffset</samp>
| ''(Optional)'' When the <samp>Type</samp> field is set to <samp>Television</samp>, the X and Y pixel offset relative to the TV's bounding box to apply when drawing the screen image onto the TV. Default none.
|-
|-
| <samp>RepeatingChanceKey</samp>
| <samp>TelevisionScreenScale</samp>
| ''(Optional)'' When checking the <samp>RepeatingChance</samp> field, use this to seed a predictable RNG. This can be used to synchronize separate drops. Default none.
| ''(Optional)'' When the <samp>Type</samp> field is set to <samp>Television</samp>, the zoom multiplier to apply to the screen image so it fits onto the TV's screen.
 
This can optionally contain the <code>%RANDOM_KEY</code> token, which is set to a unique identifier for this monster during the current tick.
|-
|-
| <samp>ExplodeStack</samp>
!colspan="2"| advanced
| ''(Optional)'' Whether to split multi-item stacks into single-item stacks. Default false.
 
For example, let's say a monster would drop a stack of 15 wood. With this option enabled, it would instead drop 15 stacks of one wood each.
|-
|-
| <samp>SkipIfDropped</samp>
| <samp>CustomFields</samp>
| ''(Optional)'' Skip the current entry if one of these drop IDs have already been dropped. Default none.
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
|}


This is specified as an array. For example:
===[[Modding:Hats|<samp>Data/Hats</samp>]]===
<syntaxhighlight lang="js">
This has been overhauled into a data model asset, with translations moved into a new <samp>Strings/Hats</samp> asset. This also includes new fields like <samp>ContextTags</samp> and <samp>CustomFields</samp> which weren't available in the old format.
"SkipIfDropped": [ "ExampleDropId", "AnotherDropId" ]
</syntaxhighlight>
|}
|-
!colspan="2"| variants
|-
| <samp>DefaultVariant</samp>
| ''(Optional)'' When the game creates a monster of this type without specifying a variant, use the given variant instead of creating it from only the base data. Default false.
|-
| <samp>Variants</samp>
| ''(Optional)'' The possible variations of this monster. Default none.


Each variant is simply a set of fields which override the base data when set. For example, this creates a variant which only differs from the base monster by name and health points:
The data asset now consists of a string → model lookup, where...
<syntaxhighlight lang="js">
* The key is the [[Modding:Common data field types#Item ID|unqualified item ID]].
"Variants": [
* The value is a model with the fields listed below.
    {
        "DisplayName": "{{i18n: variant-name}}",
        "Health": 50
    }
</syntaxhighlight>


This consists of a list of models with these fields:
{| class="wikitable"
{| class="wikitable"
|-
|-
Line 485: Line 481:
! effect
! effect
|-
|-
| ''monster fields''
!colspan="2"| basic info
| All monster fields (except <samp>DefaultVariant</samp> and <samp>Variants</samp>) can be set on the variant. All fields are optional, and default to the value set in the monster's base data.
|-
|-
| <samp>InheritDrops</samp>
| <samp>Name</samp>
| ''(Optional)'' Whether to inherit drops defined in the monster's base <samp>Drops</samp> field. Default true.
| The internal item name (not shown in-game).
|-
| <samp>DisplayName</samp><br /><samp>Description</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name and description.
|-
| <samp>HairStyle</samp>
| ''(Optional)'' What to do about the player's hair when they wear this hat. Default <samp>DrawObscuredHair</samp>.


Specifically:
The possible values are:
* If <samp>true</samp>, the variant will combine the base <samp>Drops</samp> and variant <samp>Drops</samp> into one list.
* <samp>DrawFullHair</samp>: the hair is drawn like usual (e.g. for hats that don't hide the hair like [[Abigail's Bow|Abigail's bow]]).
* If <samp>false</samp>, only drops in the variant <samp>Drops</samp> field are applied.
* <samp>DrawObscuredHair</samp>: the hair is partly obscured under the hat (e.g. for most hats like the [[Cowboy Hat|cowboy hat]]).
|}
* <samp>HideHair</samp>: the hair is fully hidden (e.g. for hats which fully cover the head like the [[Mummy Mask|mummy mask]]).
|-
|-
!colspan="2"| advanced
| <samp>SkipHairOffset</samp>
| ''(Optional)'' Whether to skip offsetting the hat to sit 'on top' of the player's current hairstyle (e.g. for masks). Default false.
|-
|-
| <samp>CustomFields</samp>
| <samp>Texture</samp>
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
| The [[Modding:Common data field types#Asset name|asset name]] for the texture containing the hat sprite. Defaults to <samp>Characters/Farmer/hats</samp> if omitted, but should always be specified for custom hats.
|}
|-
 
| <samp>SpriteIndex</samp>
For example, this [[Modding:Content Patcher|Content Patcher code]] adds a new 'Pufferchick' monster which drops pufferfish when defeated. The monster's spritesheet is automatically loaded from <samp>Monsters/&lt;ID&gt;</samp>.
| ''(Optional)'' The sprite's index within the <samp>Texture</samp>, where 0 is the top-left sprite. Default 0.
 
|-
'''Note:''' this only adds the monster data. Currently this does nothing unless you have another mod which spawns instances of the monster in-game.
| <samp>ContextTags</samp>
| ''(Optional)'' The custom [[Modding:Context tags|context tags]] to add for this item (in addition to the tags added automatically based on the other item data), specified as an array.
|-
| <samp>CustomFields</samp>
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
|}
 
For example, here's how to add a new hat in 1.7:
{{Content Patcher example|<nowiki>
{{Content Patcher example|<nowiki>
     "Changes": [
     "Changes": [
Line 510: Line 519:
         {
         {
             "Action": "EditData",
             "Action": "EditData",
             "Target": "Data/Monsters",
             "Target": "Data/Hats",
             "Entries": {
             "Entries": {
                 "{{ModId}}_Pufferchick": {
                 "{{ModId}}_FancyHat": {
                     "DisplayName": "{{i18n: pufferchick.name}}",
                     "Name": "{{ModId}}_FancyHat",
                     "ExperiencePoints": 3,
                     "DisplayName": "{{i18n: fancy-hat.name}}",
 
                     "Description": "{{i18n: fancy-hat.description}}",
                    "Health": 30,
                     "HairStyle": "DrawObscuredHair",
                    "Attack": 2,
                     "Texture": "Mods/{{ModId}}/Hats",
                     "Defense": 5,
                    "SpriteIndex": 0
                    "DodgeChance": 0.3,
                     "Speed": 2,
                    "DetectionDistance": 2,
 
                     "Drops": [
                        {
                            "Id": "Pufferfish",
                            "ItemId": "(O)128",
                            "Chance": 0.5,
                            "RepeatingChance": 0.1
                        }
                    ]
                 }
                 }
             }
             }
Line 538: Line 535:
         {
         {
             "Action": "Load",
             "Action": "Load",
             "Target": "Monsters/{{ModId}}_Pufferchick",
             "Target": "Mods/{{ModId}}/Hats",
             "FromFile": "assets/pufferchick.png"
             "FromFile": "assets/hats.png"
         }
         }
     ]
     ]
</nowiki>}}
</nowiki>}}


===[[Modding:Objects|<samp>Data/Objects</samp>]]===
===[[Modding:Monster data|<samp>Data/Monsters</samp>]]===
Added one new field:
Monster data has been completely rethought in Stardew Valley 1.7. In particular...
 
* For monster data in general:
{| class="wikitable"
** <samp>Data/Monsters</samp> has been been overhauled into a data model asset, with translations moved into a new <samp>Strings/Monsters</samp> asset. This includes significant new features which weren't supported with the old format.
|-
** A new 'monster variant' concept lets multiple specific monsters share common data (e.g. <samp>Green Slime</samp> and <samp>Tiger Slime</samp> are variants of the new base <samp>Slime</samp> monster). This is particularly used for common drops.
! field
** A new 'monster tag' system lets monster define custom tags like <samp>slime_is_prismatic</samp>, which can be used to filter monster drops.
! effect
* For monster drops:
|-
** A rethought monster drop system supports the full range of vanilla features like [[Modding:Game state queries|conditions]], [[Modding:Item queries|item queries]], [[Modding:Common data field types#Item ID|qualified item IDs]] for non-object drops, and monster-specific concepts like repeating drop chance and mutually-exclusive drops.
| <samp>Buffs</samp>
** All drops are now [[Modding:Common data field types#Item ID|qualified item IDs]]. The former 'resource IDs' (formatted as negative numbers like <samp>-4</samp>) are no longer supported; items are converted into their equivalent resource debris automatically where needed.
| This field already existed, but has a field change:
** Nearly all monster drops are now defined in <samp>Data/Monsters</samp> (with just a few hardcoded drops common to all monsters left).
 
The data asset now consists of a string → model lookup, where...
* The key is the [[Modding:Common data field types#Unique string ID|unique string ID]].
* The value is a model with the fields listed below.
 
{| class="wikitable"
{| class="wikitable"
|-
|-
Line 559: Line 561:
! effect
! effect
|-
|-
| <samp>CustomAttributes</samp>
!colspan="2"| basic info
| This field already existed, but has one new field:
|-
{| class="wikitable"
| <samp>DisplayName</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the monster's display name.
|-
|-
! field
| <samp>IsGlider</samp>
! effect
| ''(Optional)'' Whether the monster is flying (e.g. so they glide over obstacles). Default false.
|-
|-
| <samp>CustomFields</samp>
| <samp>IsMineMonster</samp>
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
| ''(Optional)'' Whether this monster spawns in the mines, and should be buffed after the player reaches the bottom. This sometimes applies to monsters that can appear elsewhere too (e.g. [[Wilderness Golem|wilderness golems]] on the farm receive mine buffs too). Default false.
|}
|}
|}
 
===[[Modding:Special orders|<samp>Data/SpecialOrders</samp>]]===
<ul>
<li>Added one new field:
{| class="wikitable"
|-
|-
! field
| <samp>ExperiencePoints</samp>
! effect
| ''(Optional)'' The combat [[Skills|experience points]] received for defeating the monster. Default 1.
|-
|-
| <samp>CanBeCancelled</samp>
!colspan="2"| stats
| ''(Optional)'' Whether the special order can be cancelled. In multiplayer, any player cancelling the special order will remove it for all players. Default false.
|}
 
And improved one field:
{| class="wikitable"
|-
|-
! field
| <samp>Health</samp>
! effect
| ''(Optional)'' The initial hit points. Default 20.
|-
|-
| <samp>Duration</samp>
| <samp>Attack</samp>
| This can now be set to <samp>"Indefinite"</samp> for a special order with no expiry. It will remain active until it's completed or cancelled. Consider enabling <samp>CanBeCancelled</samp> if applicable.
| ''(Optional)'' The attack power (i.e. how much damage its hits inflict on players). Default 5.
|}
</ul>
 
===[[Modding:Tools|<samp>Data/Tools</samp>]]===
Added one field:
{| class="wikitable"
|-
|-
! field
| <samp>Defense</samp>
! effect
| ''(Optional)'' The defense which reduces damage received by this monster. Default 0.
|-
| <samp>DodgeChance</samp>
| ''(Optional)'' The percentage chance that the monster dodges an attack, as a value between 0 (never) and 1 (always). Default 0.
|-
| <samp>Speed</samp>
| ''(Optional)'' The default movement speed. Default 1.
|-
| <samp>Jitteriness</samp>
| ''(Optional)'' How often the monster will move in random non-player directions to try to get around objects, as a value between 0 (never) and 1 (always). Default 0.1.
|-
| <samp>DetectionDistance</samp>
| ''(Optional)'' The distance at which the monster detects a player and begins moving towards them, or -1 for unlimited. Default 4.
|-
!colspan="2"| drops
|-
|-
| <samp>ContextTags</samp>
| <samp>Drops</samp>
| ''(Optional)'' The custom [[Modding:Context tags|context tags]] to add for this item (in addition to the tags added automatically based on the other item data), specified as an array.
| ''(Optional)'' The items which can drop when the monster is defeated. Default none.
|}
 
All matching entries are dropped. If the player has a [[Burglar's Ring|burglar's ring]] equipped, each entry will make two attempts to drop (but fields like <samp>RepeatingChance</samp> and <samp>SkipIfDropped</samp> are independent between the two attempts).


===[[Modding:Weapons|<samp>Data/Weapons</samp>]]===
This consists of a list of models with these fields:
Added one field:
{| class="wikitable"
{| class="wikitable"
|-
|-
Line 613: Line 611:
! effect
! effect
|-
|-
| <samp>ContextTags</samp>
| ''common fields''
| ''(Optional)'' The custom [[Modding:Context tags|context tags]] to add for this item (in addition to the tags added automatically based on the other item data), specified as an array.
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for monster drops.
|}


==Changes for all mod authors==
Notes:
===[[Modding:Context tags|Context tag]] changes===
* If a drop has an [[Modding:Item queries|item query]] which returns multiple item stacks, one of them will be selected at random.
Added new context tags:
* The <samp>Condition</samp> field can optionally contain the <code>%RANDOM_KEY</code> token, which is set to a unique identifier for this monster during the current tick.
{| class="wikitable"
|-
| <samp>ForTags</samp>
| ''(Optional)'' The monster tags for which this drop applies. This can be a [[Modding:Context tags|context tag]]-like query string like <samp>!variant_frost_bat, !variant_lava_bat</samp> (not [[Frost Bat|frost bat]] or [[Lava Bat|lava bat]]). Default none, meaning it applies to all monsters with this data.
|-
|-
! context tag
| <samp>Chance</samp>
! item types
| ''(Optional)'' A probability that this item will be found, as a value between 0 (never) and 1 (always). Default 1.
! effect
|-
|-
| <samp>axe</samp><br /><samp>error_tool</samp><br /><samp>fishing_rod</samp><br /><samp>generic_tool</samp><br /><samp>hoe</samp><br /><samp>lantern</samp><br /><samp>melee_weapon</samp><br /><samp>milk_pail</samp><br /><samp>pan</samp><br /><samp>pickaxe</samp><br /><samp>raft</samp><br /><samp>shears</samp><br /><samp>slingshot</samp><br />[[Return Scepter|<samp>wand</samp>]]<br /><samp>watering_can</samp>
| <samp>RepeatingChance</samp>
| [[Modding:Tools|tools]] and [[Modding:Weapons|weapons]]
| ''(Optional)'' A compounding probability of an extra drop, as a value between 0 (never) and .95 (nearly always). Default 0.
| The C# type which implements the tool or melee weapon.


Note that the vanilla scythes are <samp>melee_weapon</samp>.
This applies after an item has been dropped based on the other fields. This chance is repeatedly checked to produce an extra drop until it fails. Each repeat drop will ignore the <samp>Chance</samp> and <samp>Condition</samp> fields, but reapply all other item spawn fields (e.g. re-selecting <samp>RandomItemId</samp> if applicable).
|-
|-
| <samp>fish_skip_minigame</samp>
| <samp>RepeatingChanceKey</samp>
| ''any''
| ''(Optional)'' When checking the <samp>RepeatingChance</samp> field, use this to seed a predictable RNG. This can be used to synchronize separate drops. Default none.
| If the player catches this item while fishing, it'll be caught directly without the fishing minigame. This matches the behavior when catching junk items like [[seaweed]] (which now have the context tag where needed).
 
This can optionally contain the <code>%RANDOM_KEY</code> token, which is set to a unique identifier for this monster during the current tick.
|-
|-
| <samp>ignore_gift_limits</samp>
| <samp>ExplodeStack</samp>
| ''any giftable item''
| ''(Optional)'' Whether to split multi-item stacks into single-item stacks. Default false.
| Whether this item ignores the gift limits when given as a gift (similar to [[Stardrop Tea|stardrop tea]]). Items with this tag don't count towards the daily/weekly limits, and can be given even if those limits have been reached.
 
For example, let's say a monster would drop a stack of 15 wood. With this option enabled, it would instead drop 15 stacks of one wood each.
|-
|-
| <samp>is_galaxy_weapon</samp>
| <samp>SkipIfDropped</samp>
| [[Modding:Weapons|weapons]]
| ''(Optional)'' Skip the current entry if one of these drop IDs have already been dropped. Default none.
| Marks the tool as a galaxy weapon like the [[Galaxy Hammer|galaxy hammer]] or [[Galaxy Sword|galaxy sword]]. This is set for vanilla scythes through <samp>Data/Weapons</samp>. This affects logic which checks for galaxy weapons (e.g. [[Galaxy Soul|galaxy soul]] enchantments).
 
This is specified as an array. For example:
<syntaxhighlight lang="js">
"SkipIfDropped": [ "ExampleDropId", "AnotherDropId" ]
</syntaxhighlight>
|}
|-
|-
| <samp>is_scythe</samp>
!colspan="2"| tags
| [[Modding:Tools|tools]] and [[Modding:Weapons|weapons]]
| Marks the tool as a [[scythe]]. This is set for vanilla scythes through <samp>Data/Weapons</samp>.
|-
|-
| <samp>spawns_butterflies</samp>
| <samp>ContextTags</samp>
| [[Modding:Furniture|furniture]]
| ''(Optional)'' The [[Modding:Context tags|context tags]] to add for this monster, in addition to those added automatically based on the other fields. Default none.
| Whether butterflies spawn around this furniture, similar to the [[Butterfly Hutch|butterfly hutch]].
|-
|-
| <samp>upgrade_level_*</samp>
!colspan="2"| variants
| [[Modding:Tools|tools]] and [[Modding:Weapons|weapons]]
| The tool upgrade level. These tags are added automatically based on the tool's current level. For example, a copper [[axe]] will have both <samp>upgrade_level_0</samp> (base axe) and <samp>upgrade_level_1</samp> (copper axe).
|}
 
===[[Modding:Console commands|Debug command]] changes===
Improved existing commands:
 
{| class="wikitable"
|-
|-
! command
| <samp>DefaultVariant</samp>
! description
| ''(Optional)'' When the game creates a monster of this type without specifying a variant, use the given variant instead of creating it from only the base data. Default false.
|-
|-
| <samp>jump</samp>
| <samp>Variants</samp>
| Fixed error if the NPC doesn't exist.
| ''(Optional)'' The possible variations of this monster. Default none.
|-
 
| <samp>perfection</samp>
Each variant is simply a set of fields which override the base data when set. For example, this creates a variant which only differs from the base monster by name and health points:
| Fixed error when run on a save which already has some requirements partly met.
<syntaxhighlight lang="js">
|}
"Variants": [
    {
        "DisplayName": "{{i18n: variant-name}}",
        "Health": 50
    }
</syntaxhighlight>


===[[Modding:Dialogue|Dialogue]] changes===
This consists of a list of models with these fields:
<ul>
<li>Added a new [[Modding:Dialogue#Special tokens|special token]] in dialogue strings:
{| class="wikitable"
{| class="wikitable"
|-
|-
! token
! field
! description
! effect
|-
| ''monster fields''
| All monster fields (except <samp>DefaultVariant</samp> and <samp>Variants</samp>) can be set on the variant. All fields are optional, and default to the value set in the monster's base data.
|-
|-
| <code>&#124;&#124;&#124;</code>
| <samp>InheritDrops</samp>
| Stands for "randomizeDelimiter". Delimits an arbitrary number of dialogue variants from which to choose each day. After randomization, any leading or trailing whitespace is trimmed. This randomization is deterministic per day (e.g. reloading the save won't change which one is shown).
| ''(Optional)'' Whether to inherit drops defined in the monster's base <samp>Drops</samp> field. Default true.


For example, let's say you did this:
Specifically:
<syntaxhighlight lang="js">
* If <samp>true</samp>, the variant will combine the base <samp>Drops</samp> and variant <samp>Drops</samp> into one list.
"Rainy_Night": "
* If <samp>false</samp>, only drops in the variant <samp>Drops</samp> field are applied.
    I love rain.$h|||
|}
    I like rain.$h|||
    I adore rain.$h|||
    I hate rain.$s#$b#Just kidding. I love it!$h|||
    I enjoy rain.$h
"
</syntaxhighlight>
 
That would create five variants of the dialogue which each have an equal probability of being selected.
|}</li>
<li>Added new dialogue keys:
{| class="wikitable"
|-
|-
! key
!colspan="2"| advanced
! description
|-
|-
| ''passive festival dialogue''
| <samp>CustomFields</samp>
| Identical to [[Modding:Dialogue#Location dialogue|location dialogue]], but you can use the passive festival ID as the location name. Any passive festival dialogue has priority over location dialogue in the same location.
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
|}</li>
|}
<li>Improved some [[Modding:Dialogue#Special tokens|special tokens]]:
 
{| class="wikitable"
For example, this [[Modding:Content Patcher|Content Patcher code]] adds a new 'Pufferchick' monster which drops pufferfish when defeated. The monster's spritesheet is automatically loaded from <samp>Monsters/&lt;ID&gt;</samp>.
|-
! token
! changes
|-
| <code>&#124;&#124;</code>
| Whitespace around the token is now ignored, so you can split text into multiple lines:
<syntaxhighlight lang="js">
"Wed8": "
    Isn't it expensive, coming to the desert so often like you do?#$e#You must really like to see me, huh? Hmmm... $h||
    *sigh*... I do miss the beautiful flowers of Stardew Valley...$s
"
</syntaxhighlight>
|}</li>
<li>Some dialogues were merged or renamed using the new features. The previous dialogue keys are now ignored by the game.


{| class="wikitable"
'''Note:''' this only adds the monster data. Currently this does nothing unless you have another mod which spawns instances of the monster in-game.
|-
{{Content Patcher example|<nowiki>
! asset
    "Changes": [
! former key
        // add data
! changes
        {
|-
            "Action": "EditData",
| <samp>Characters/Dialogue/{{t|NPC name}}</samp>
            "Target": "Data/Monsters",
| <samp><samp>Resort_{{t|number}}</samp><br /><samp>Resort_Bar_{{t|number}}</samp><br /><samp>Resort_Chair_{{t|number}}</samp><br /><samp>Resort_Dance_{{t|number}}</samp><br /><samp>Resort_Shore_{{t|number}}</samp><br /><samp>Resort_Towel_{{t|number}}</samp><br /><samp>Resort_Umbrella_{{t|number}}</samp><br /><samp>Resort_Wander_{{t|number}}</samp>
            "Entries": {
| Merged into their base key (e.g. <samp>Resort_{{t|random}}</samp> into <samp>Resort</samp>) using the new <code>&#124;&#124;&#124;</code> random-variant token.
                "{{ModId}}_Pufferchick": {
|-
                    "DisplayName": "{{i18n: pufferchick.name}}",
|rowspan="7"| <samp>Characters/Dialogue/MarriageDialogue</samp><br /><samp>Characters/Dialogue/MarriageDialogue{{t|NPC name}}</samp><br /><samp>Characters/Dialogue/MarriageDialogue{{t|NPC name}}Roommates</samp>
                    "ExperiencePoints": 3,
| <samp>funLeave_{{t|NPC name}}</samp><br /><samp>funReturn_{{t|NPC name}}</samp><br /><samp>jobLeave_{{t|NPC name}}</samp><br /><samp>jobReturn_{{t|NPC name}}</samp><br /><br /><samp>patio_{{t|NPC name}}</samp><br /><samp>spouseRoom_{{t|NPC name}}</samp><br /><br /><samp>spring_{{t|NPC name}}</samp><br /><samp>summer_{{t|NPC name}}</samp><br /><samp>fall_{{t|NPC name}}</samp><br /><samp>winter_{{t|NPC name}}</samp>
 
| Moved into <samp>MarriageDialogue{{t|NPC name}}</samp> and removed the NPC suffix (like <samp>spouseRoom_{{t|NPC name}}</samp> → <samp>spouseRoom</samp>).
                    "Health": 30,
|-
                    "Attack": 2,
| <samp>Indoor_Day_0</samp><br /><samp>Indoor_Day_1</samp><br /><samp>Indoor_Day_2</samp><br /><samp>Indoor_Day_3</samp><br /><samp>Indoor_Day_4</samp>
                    "Defense": 5,
| Merged into <samp>Indoor_Day</samp>.
                    "DodgeChance": 0.3,
|-
                    "Speed": 2,
| <samp>Indoor_Night_0</samp><br /><samp>Indoor_Night_1</samp><br /><samp>Indoor_Night_2</samp><br /><samp>Indoor_Night_3</samp><br /><samp>Indoor_Night_4</samp><br /><samp>Indoor_Night_{{t|NPC name}}</samp>
                    "DetectionDistance": 2,
| Merged into <samp>Indoor_Night</samp>.
 
|-
                    "Drops": [
| <samp>NoBed_0</samp><br /><samp>NoBed_1</samp><br /><samp>NoBed_2</samp><br /><samp>NoBed_3</samp>
                        {
| Merged into <samp>NoBed</samp>.
                            "Id": "Pufferfish",
                            "ItemId": "(O)128",
                            "Chance": 0.5,
                            "RepeatingChance": 0.1
                        }
                    ]
                }
            }
        },
 
        // add texture
        {
            "Action": "Load",
            "Target": "Monsters/{{ModId}}_Pufferchick",
            "FromFile": "assets/pufferchick.png"
        }
    ]
</nowiki>}}
 
===[[Modding:Schedule data|Schedule data]]===
Schedules have been changed into data models. Previously under <samp>Characters/schedules</samp>, now under <samp>Characters/ScheduleData</samp>.
 
{| class="wikitable"
|-
|-
| <samp>Outdoor_0</samp><br /><samp>Outdoor_1</samp><br /><samp>Outdoor_2</samp><br /><samp>Outdoor_3</samp><br /><samp>Outdoor_4</samp><br /><samp>Outdoor_{{t|NPC name}}</samp>
! field
| Merged into <samp>Outdoor</samp>.
! effect
|-
|-
| <samp>Rainy_Day_0</samp><br /><samp>Rainy_Day_1</samp><br /><samp>Rainy_Day_2</samp><br /><samp>Rainy_Day_3</samp><br /><samp>Rainy_Day_4</samp>
| <samp>Precedence</samp>
| Merged into <samp>Rainy_Day</samp>.
| The precedence of this entry. A higher precedence will be checked first.
 
Note: the hardcoded schedules for visiting [[Ginger Island]] will override everything below precedence <samp>100000</samp>.
|-
| <samp>Season</samp>
| ''(Optional)'' The season that this schedule applies to, if any. If not specified, applies to any season.
|-
| <samp>DayOfMonth</samp>
| ''(Optional)'' The day of month that this schedule applies to, if any. If not specified, applies to any day of the month.
|-
|-
| <samp>Rainy_Night_0</samp><br /><samp>Rainy_Night_1</samp><br /><samp>Rainy_Night_2</samp><br /><samp>Rainy_Night_3</samp><br /><samp>Rainy_Night_4</samp><br /><samp>Rainy_Night_5</samp><br /><samp>Rainy_Night_{{t|NPC name}}</samp>
| <samp>WeekDay</samp>
| Merged into <samp>Rainy_Night</samp>.
| ''(Optional)'' The week day that this schedule applies to, if any. If not specified, applies to any day of the week.
|}</li>
<li>Fixed <samp>{{t|location}}_{{t|x}}_{{t|y}}</samp> and <samp>{{t|location}}_{{t|dayOfWeek}}</samp> dialogue keys never used in 1.6.0+ if a player has at least two hearts with the NPC.</li>
<li>Fixed [[Modding:Dialogue#Location dialogue|location dialogues]] not recognizing the <samp>spring</samp> prefix (they only allowed <samp>summer</samp>, <samp>fall</samp>, and <samp>winter</samp>).</li>
<li>Fixed <samp>$r</samp> response IDs not tracked correctly if you reuse an NPC reaction key across multiple <samp>$r</samp> options.</li>
</ul>


===Enchantment data===
This accepts the short name of the day of week, ex. <samp>Mon</samp>, <samp>Tue</samp>, <samp>Wed</samp>, ...
[[Forge#Enchantments|Enchantments]] have been '''partly''' de-hardcoded into a new <samp>Data/Enchantments</samp> data asset. Mods can now easily add new enchantments, including enchantments applied through the [[forge]] using a [[Prismatic Shard|prismatic shard]] or a custom item ID.
|-
| <samp>RequiredHearts</samp>
| ''(Optional)'' The minimum amount of friendship (in hearts) for this schedule to apply, if any. If not specified, applies regardless of friendship level.
|-
| <samp>Condition<samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] for if this entry should apply, in addition to the other fields. If not specified, treated as <samp>TRUE</samp>.
|-
| <samp>StartLocationOverride<samp>
| ''(Optional)'' Override the location to start the day in when this schedule is chosen. <samp>StartTileOverride</samp> must also be specified for this to apply.


However, this logic is still hardcoded:
Requires <samp>StartTileOverride</samp> to be specified for this to work.
* Forging [[Forge#Innate enchantments|innate enchantments]]. The innate enchantments are in data, but the logic to choose which to apply is still hardcoded.
|-
* Forging [[diamond]]s into a weapon to fill all its [[Forge#Weapon forging|weapon stat slots]].
| <samp>StartTileOverride<samp>
* Forging three [[Galaxy Soul|galaxy souls]] into galaxy weapons to transform them into infinity weapons. (The 'Galaxy Soul' enchantment is in data, but the transformation is hardcoded.)
| ''(Optional)'' Override the tile to start the day on when this schedule is chosen. <samp>StartLocationOverride</samp> must also be specified for this to apply.
* Several enchantments' effects when applied (though weapon buff effects are in data).


This consists of a string → model lookup, where...
Requires <samp>StartLocationOverride</samp> to be specified for this to work.
* The key is the [[Modding:Common data field types#Unique string ID|unique string ID]] for the enchantment.
|-
* The value is a model with the fields listed below.
| <samp>StartFacingDirectionOverride<samp>
| ''(Optional)'' Override the facing direction to start the day with when this schedule is chosen. <samp>StartLocationOverride</samp> must also be specified for this to apply.


{| class="wikitable"
Requires <samp>StartLocationOverride</samp> to be specified for this to work.
|-
|-
! field
| <samp>StartEndOfRouteAnimation<samp>
! effect
| ''(Optional)'' Override the end of route animation to start the day with when this schedule is chosen. <samp>StartLocationOverride</samp> must also be specified for this to apply.
 
Requires <samp>StartLocationOverride</samp> to be specified for this to work.
|-
|-
| <samp>DisplayName</samp>
| <samp>StartEndOfRouteMessage<samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the enchantment's display name, shown in tooltips. This can contain <samp>{0}</samp> for the enchantment level, if applicable.
| ''(Optional)'' Override the end of route message to start the day with when this schedule is chosen. <samp>StartLocationOverride</samp> must also be specified for this to apply.
 
Requires <samp>StartLocationOverride</samp> to be specified for this to work.
|-
|-
| <samp>ForgeWith</samp>
| <samp>FallbackSchedules<samp>
| ''(Optional)'' If set, this enchantment is applied to tools by [[Forge|forging]] an item with this qualified ID into it. Default none, in which case it won't be applicable through the forge.
| ''(Optional)'' A list of additional schedules options that, if the corresponding GSQ passes, will revert to that schedule instead. Intended for "fail conditions" (ex. one of the locations in this schedule are not currently accessible).
{| class="wikitable"
|-
|-
| <samp>AppliesTo</samp>
! field
| ''(Optional)'' The tools or weapons to which this enchantment can be applied. Defaults to all tools/weapons.
! effect
 
This is specified as an array of [[Modding:Context tags|context tag]] queries. The enchantment can be applied if at least one query matches.
<syntaxhighlight lang="js">
"AppliesTo": [
    "melee_weapon, !is_scythe", // any non-scythe melee weapon
    "hoe, upgrade_level_4"      // any hoe upgraded to iridium or higher
]
</syntaxhighlight>
|-
|-
| <samp>IsForge</samp>
| <samp>Condition</samp>
| ''(Optional)'' Whether this is a [[Forge#Weapon forging|weapon stat enchantment]] applied through the [[forge]]. Default false.
| The [[Modding:Game state queries|game state query]] to check for this fallback option.
|-
|-
| <samp>IsSecondary</samp>
| <samp>Schedule</samp>
| ''(Optional)'' Whether this is an [[Forge#Innate enchantments|innate enchantment]] applied through the [[forge]] using a [[Dragon Tooth|dragon tooth]]. Default false.
| The schedule to use if the condition passed for this fallback option.
 
If this is "season", it will act check "spring", "summer", "fall", or "winter" based on the current game's season.
IF this is "no_schedule", then the NPC will have no schedule for that day.
|-
|-
| <samp>IsVisible</samp>
| <samp>CustomFields</samp>
| ''(Optional)'' Whether the enchantment should be shown in the tool/weapon's tooltip. Default true.
| ''(Optional)'' Custom fields for mods to use.
|}
|-
|-
| <samp>MaximumLevel</samp>
| <samp>Commands</samp>
| ''(Optional)'' The number of times this enchantment can be applied to the same tool to upgrade the enchantment level (e.g. for [[Forge#Weapon forging|weapon stat enchantments]]). A value of 1 means there's only one enchantment level, so it can't be upgraded by applying the enchantment again. Default 1.
| A list of commands for the schedule.
{| class="wikitable"
|-
! field
! effect
|-
|-
| <samp>EquipmentEffects</samp>
| <samp>Type</samp>
| ''(Optional)'' The buffs applied to the weapon when this enchantment is applied.
| ''(Optional)'' The type of this schedule command. Defaults to <samp>Depart</samp>
 
This consists of a list of models with the fields below. You can specify any number of entries; the first one which matches the tool will be applied.
{| class="wikitable"
{| class="wikitable"
|-
|-
! field
! type
! effect
! meaning
|-
|-
| <samp>Id</samp>
| <samp>Depart</samp>
| A [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry.
| The NPC will depart at the specified time.
|-
|-
| <samp>MinLevel</samp>
| <samp>Arrive</samp>
| ''(Optional)'' The minimum enchantment level for which these stats apply. Default 0 (i.e. any level).
| The NPC will try to arrive at the specified time.
|-
|-
| ''other fields''
| <samp>Bed</samp>
| See the <samp>Effects</samp> field [[Modding:Buffs|in <samp>Data/Buffs</samp>]], which is equivalent to this model.
| The NPC will try to return to their bed.
|}
|}
|-
|-
!colspan="2"| advanced
| <samp>Time</samp>
| The time for this schedule command. This must be a time '''after''' the previous command's time.
 
Note: a time of <samp>0</samp> (for "0 schedules") is no longer supported. For the equivalent behavior, use <samp>StartLocationOverride</samp> and friends.
|-
| <samp>DestinationLocation</samp>
| ''(Only applies for <samp>Type</samp> = <samp>Depart</samp> or <samp>Arrive</samp>)'' The location that this command takes the NPC to.
|-
| <samp>Destination</samp>
| ''(Only applies for <samp>Type</samp> = <samp>Depart</samp> or <samp>Arrive</samp>)'' The tile in the location that this command takes the NPC to.
|-
|-
| <samp>CustomFields</samp>
| <samp>DestinationFacingDirection</samp>
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
| ''(Optional, only applies for <samp>Type</samp> = <samp>Depart</samp> or <samp>Arrive</samp>))'' The facing direction that should be used when arriving at this command's target.  
|-
|-
| <samp>ClassName</samp>
| <samp>EndOfRouteAnimation</samp>
| ''(Optional, specialized)'' The name of the C# class to construct within the <code>StardewValley.Enchantments</code> namespace. The class must be a subclass of <samp>StardewValley.Enchantments.Enchantment</samp>, and have a constructor with no arguments. For example, given a value of <samp>BottomlessEnchantment</samp>, the game will create <code>StardewValley.Enchantments.BottomlessEnchantment</code> instances.
| ''(Optional)'' The animation from <samp>Data/animationDescriptions</samp> to play upon ending this NPC.
 
|-
This should usually be omitted, in which case the game will create a generic <samp>Enchantment</samp> instance which uses the data in <samp>Data/Enchantments</samp> for its ID.
| <samp>EndOfRouteMessage</samp>
| ''(Optional)'' The localized string key to say if a player talks to this NPC after ending this command, but before the next one.
|-
| <samp>CustomFields</samp>
| ''(Optional)'' Custom fields for mods to use.
|}
|}
===[[Modding:Event data|Event]] changes===
====Multilingual events====
All vanilla events are now multilingual, with a single copy of each event script which uses translation keys. Translations from the old per-language event files were moved into a per-language <samp>Strings/Events</samp> file.
For example:
{| class="wikitable"
|-
|-
! files in 1.6.15
| <samp>CustomFields</samp>
! files in 1.6.16
| ''(Optional)'' Custom fields for mods to use.
|-
| <pre>
Data/Events/Beach
Data/Events/Beach.de-DE
Data/Events/Beach.es-ES
Data/Events/Beach.fr-FR
Data/Events/Beach.hu-HU
Data/Events/Beach.it-IT
Data/Events/Beach.ja-JP
Data/Events/Beach.ko-KR
Data/Events/Beach.pt-BR
Data/Events/Beach.ru-RU
Data/Events/Beach.tr-TR
Data/Events/Beach.zh-CN
</pre>
|valign="top"| <pre>
Data/Events/Beach
</pre>
|}
|}


[[Modding:Content Patcher|Content Patcher]] content packs should generally be unaffected, since their edits were applied to the active version of the file automatically (which will just become the base file in all languages).
The vanilla schedules were all converted using [https://gist.github.com/spacechase0/266daa4d6d916607bec235c55653fa6b this automated script], which is under the MIT license.


In rare cases, a mod which directly targets a specific localized asset name like <code>Data/Events/Beach.fr-FR</code> may no longer work or break vanilla events (depending on how it edits them). That should be a very rare case, since the APIs for both Content Patcher and SMAPI were designed to discourage doing that.
===[[Modding:Objects|<samp>Data/Objects</samp>]]===
 
Added new fields:
====Forking deprecated====
All vanilla events which used forking now use [[#New event commands|goto labels]] instead.
 
'''Forking still works like before''' for backwards compatibility, but mod events should prefer goto labels since...
* they work more consistently and intuitively with other features like skip labels;
* it's the approach that the game will be applying and developing in future versions;
* deprecated commands will be reported as an error if you use the [[#EventValidator|<samp>EventValidator</samp>]];
* and there's no guarantee forking will always work in future versions.
 
The [[#Deprecated commands|fork-related event commands are deprecated]].
 
====Precondition slash now required for numeric event IDs====
In Stardew Valley 1.6.0–15, the behavior of an event key with no <code>/</code> depended on whether the ID was numeric. A numeric event ID like <code>10040609</code> was treated as an event with no precondition, while a string event ID like <code>PlayerKilled</code> was treated as a manual script. In 1.6.16+, the behavior is now consistent: any event ID without a slash (like <code>10040609</code>) is treated as a manual script, and any with a slash (like <code>10040609/</code>) is treated as an event.
 
In other words:


{| class="wikitable"
{| class="wikitable"
|-
|-
! event key format
! field
! behavior in 1.6.15
! effect
! &rarr;
! behavior in 1.6.16
|-
|-
| <samp>{{t|id}}</samp>
| <samp>Buffs</samp>
| event if numeric, else manual script
| This field already existed, but has a field change:
| &rarr;
| manual script
|-
| <samp>{{t|id}}/{{o|preconditions}}</samp>
| event
| &rarr;
| event
|}
 
====New event commands====
{| class="wikitable"
{| class="wikitable"
|-
|-
! command
! field
! description
! effect
|-
|-
| <samp>addAchievement {{t|achievement ID}}</samp>
| <samp>CustomAttributes</samp>
| Unlock an [[achievement]] for the current player. The {{t|achievement ID}} can be a [[Modding:Console commands#Statistics and achievements|platform achievement ID]] (like <samp>Achievement_LocalLegend</samp>) or internal ID (like <samp>17</samp> for Gourmet Chef).
| This field already existed, but has one new field:
{| class="wikitable"
|-
|-
| <samp>addActor {{t|x}} {{t|y}} {{t|direction}}</samp>
! field
| Add a character or player to the event. This is mostly equivalent to adding them through the [[Modding:Event data#Basic format|character positions field]], but can be done at any point in the script (e.g. for use with <samp>goto</samp> for event variations).
! effect
|-
|-
| <samp>choose {{t|question}} [{{t|answer}} {{t|go to label}}]+</samp>
| <samp>CustomFields</samp>
| Show a dialogue box to choose from a list of responses, then optionally skip to a label based on the selected answer.
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
 
|}
Arguments:
|}
{| class="wikitable"
|-
|-
! argument
| <samp>UseCondition</samp>
! usage
| A [[Modding:Game state queries|game state query]] for determining if the object is usable on right click. If not specified, equivalent to <samp>"TRUE"</samp>.
|-
|-
| {{t|question}}
| <samp>UseConditionFailedMessage</samp>
| The [[Modding:Common data field types#Translation key|translation key]] or literal text to show above the choices. This can be empty (<code>""</code>) to omit the question line.
| A [[Modding:Tokenizable strings|tokenizable string]] for what message to show when <samp>UseCondition</samp> is not met. If an empty string, no message will be shown. If not specified, equivalent to <samp>"[LocalizedText Strings/UI:CantUseHere]"</samp>.
|-
|-
| {{t|answer}}
| <samp>UseActions</samp>
| The [[Modding:Common data field types#Translation key|translation key]] or literal text for an answer to show.
| A list of [[Modding:Trigger actions#Actions|actions]] to run upon using the item. These trigger actions will have an input argument called <samp>StackSize</samp>, which will be the size of the stack obtained if triggered via <samp>ConsumeOnObtain</samp>, or <samp>1</samp> otherwise. (For more information on trigger action input arguments, see the relevant section on this page.)
|-
|-
| {{t|go to label}}
| <samp>ConsumeOnUse</samp>
| If the player chooses this answer, jump to this label in the event (see the <samp>goto</samp> command for more info). This can be <code>""</code> or <code>_</code> to continue to the next command instead.
| <samp>true</samp> if the item should be consumed on use, <samp>false</samp> otherwise. Default <samp>true</samp>.
|}
 
For example, here's a simple choice which doesn't affect anything:
<pre>choose "Do you like apples?" "I love them." _ "I hate them." _/</pre>
 
Or you can change the course of the event based on the choice:
<pre>
speak Abigail "Do you... like me?$l"/
choose "" "Yes!" happy "No." heartbroken/
 
label heartbroken/
speak Abigail "Oh. I understand.$s"/
faceDirection Abigail left/
pause 3000/
end/
 
label happy/
speak Abigail "We should explore the mines together next time!$h"/
...
</pre>
|-
|-
| <samp>completeQuest {{t|id}}</samp>
| <samp>ObtainActions</samp>
| Mark a quest complete. If the quest has no reward to collect, this also removes it from the in-game journal.
| A list of [[Modding:Trigger actions#Actions|actions]] to run upon obtaining the item. These trigger actions will have an input argument called <samp>StackSize</samp>, which will be the size of the stack obtained. (For more information on trigger action input arguments, see the relevant section on this page.)
|-
|-
| <samp>conditionSpeak {{t|npc}} [{{t|dialogue}} {{o|condition}}]+</samp>
| <samp>ConsumeOnObtain</samp>
| Make an NPC say a dialogue based on arbitrary conditions. The first dialogue with a matching dialogue is spoken; if none match, the command is skipped.
| If the item should be automatically used *and* consumed when obtained. Items with this enabled:
 
<ul>
Arguments:
<li>Will not actually enter the inventory (since they are consumed immediately).</li>
{| class="wikitable"
<li>Can be collected even with a full inventory (since they are consumed immediately).</li>
<li>Will not have their <samp>UseCondition</samp> checked before their <samp>UseActions</samp> are run.</li>
<li>Will have their <samp>ObtainActions</samp> (if any) run before their <samp>UseActions</samp> are run.</li>
</ul>
|-
|-
! argument
| <samp>ShowNotificationOnObtain</samp>
! usage
| <samp>true</samp> if the item should show a notification in the bottom left corner of the screen upon receiving the item, <samp>false</samp> otherwise. Default <samp>true</samp>.
|-
|-
| {{t|npc}}
| <samp>ForgeRandomSlot</samp>
| The internal name of the NPC who should speak (which can be [[Modding:Event data#Optional NPCs|marked optional]]).
| The slot to randomize the enchantments for if this is used as an ingredient.
|-
|-
| {{t|dialogue}}
| <samp>ForgeCost</samp>
| The [[Modding:Common data field types#Translation key|translation key]] or literal text for the dialogue to speak. If omitted or empty, the command is skipped when the condition is matched.
| If greater than or equal to 0, the cinder shard cost for using this item in the forge.
|-
|-
| {{o|condition}}
| <samp>ForgeCostItem</samp>
| One of:
| If set, changes the item required for forging from cinder shards to something else.
* a [[Modding:Game state queries|game state query]];
* or <samp>ANSWERED {{t|response ID}}+</samp> as a shortcut for the <samp>PLAYER_HAS_DIALOGUE_ANSWER Current</samp> query;
* or omitted/blank to always match this dialogue if no previous one matched.
|}
|}


For example, here Maru says a different line if the player suggested she tell the truth:
===[[Modding:Weapons|<samp>Data/Weapons</samp>]]===
<pre>conditionSpeak Maru "I accidentally dropped one of the samples... I'm so sorry.$s" "ANSWERED 38" "@ came in and slammed the door so loud I dropped this sample.$u"</pre>
Added new fields:
|-
| <samp>goto [{{t|target}} {{o|condition}}]+</samp>
| Skip forward or backward to a specific position in the event script. Each {{t|target}} can be:


{| class="wikitable"
{| class="wikitable"
|-
|-
! target
! field
! description
! effect
|-
| <samp>end</samp>
| Jump to the last <samp>end</samp> event command in the script.
|-
|-
| ''any other value''
| <samp>DefaultEnchantments</samp>
| Jump to the first <samp>label</samp> command with this name.
| Enchantments to apply by default on this weapon. This is a dictionary, with the key being the enchantment ID, and the value being the level of the enchantment.
|}


You can list any number of label/[[Modding:Game state queries|condition]] pairs, and it will go to the first label with a matching condition. If a condition is omitted, it defaults to always true. If none of the conditions match, it continues to the next command normally.
Enchantments added through this are still subject to normal enchantment restrictions, and therefore must actually be applicable to this weapon.


For example, this event script uses <samp>goto</samp> to repeat a question until a specific answer is selected:
For an example of this, check out the Holy Blade.
<pre>
|}
.../
label question/
choose Abigail "Hey! Did you have your eye on someone?" "Abigail" correct "Penny" wrong "Alex" wrong/


label wrong/
==Changes for all mod authors==
speak Abigail "Oh?$u"/
===Switch blocks===
pause 500/
'Switch blocks' are a new <code>${…}$</code> syntax which can be used in nearly all game text (not just dialogue). This extends the former 'gender-switch blocks' [[Modding:Migrate to Stardew Valley 1.6#Gender changes|added in 1.6.0]].
goto question/
 
label correct/
speak Abigail \"I thought so!$l\"/
pause 500/
end
</pre>
 
You can make <samp>goto</samp> conditional using [[Modding:Game state queries|game state queries]]. For example, this will go to the <samp>divorced</samp> label if you divorced Abigail, and continue to the next command if not:
<pre>goto divorced "PLAYER_NPC_RELATIONSHIP Current Abigail Divorced"/</pre>
|-
| <samp>label {{t|label}}</samp>
| Set a named position in the event script, which you can go to using the <samp>goto</samp> command.


'''Note:''' you can't use <samp>end</samp> as a label name, since that automatically matches the <samp>end</samp> event command.
These are applied before most other commands or parsing, so you can safely use them in cases where characters like <samp>^</samp> have a different meaning (e.g. mail text).
|}


====Improved existing commands====
The supported switch blocks are:
{| class="wikitable"
{| class="wikitable"
|-
|-
! command
! type
! syntax
! description
! description
|-
|-
| <samp>gainSkill</samp>
| gender
| Added argument validation.
| <code>${male^female}</code><br /><code>${male^female^non-binary}</code>
|-
| Switch between text for male, female, and non-binary players. The non-binary value is only used if a mod overrides the player's gender, since the in-game UI only allows male or female.
| <samp>skippable</samp>
| Added an optional {{o|skip to label}} argument. If set, the event will jump to that label when the player clicks the skip button (see <samp>goto</samp> for more info). The last <samp>skippable</samp> command run before the player skips is applied.


This is meant to clean up or grant unlocks before the event ends. For example:
You can also use <samp>¦</samp> instead of <samp>^</samp>, in which case any <samp>^</samp> characters are left as-is.
<pre>
skippable beforeEnd/
.../
label beforeEnd/
gainSkill Fishing 1/
addItem (T)TrainingRod/
end
</pre>


Technically you can jump to any point in the event (e.g. to cancel the skip). However, the skip action will still cancel any ongoing event behavior like ongoing player/NPC movements, so you should be careful doing this.
For example:
<syntaxhighlight lang="json">
"Mon": "Hey ${lad^lass^kiddo}$!"
</syntaxhighlight>
|-
|-
| <samp>splitSpeak</samp>
| randomize
| You should now specify each dialogue as a separate argument (though the old syntax will still work):
| <code>${variant A &#124;&#124;&#124; …}$</code>
<pre>// in 1.6.15
| Defines an arbitrary number of variants from which to choose each day. After randomization, any leading or trailing whitespace is trimmed. This randomization is deterministic per day (e.g. reloading the save won't change which one is shown).
splitSpeak Sam "You think so?~Yeah... kids should play and have fun while they still have the chance."


// in 1.6.16
For example, let's say you did this:
splitSpeak Sam "You think so?" "Yeah... kids should play and have fun while they still have the chance."
<syntaxhighlight lang="js">
</pre>
"Rainy_Night": "I ${love ||| like ||| adore ||| somewhat enjoy ||| enjoy}$ rain.$h"
</syntaxhighlight>


This also now works with the new <samp>choose</samp> command too.
That would create five variants which each have an equal probability of being selected.
|-
| <samp>spriteText</samp>
| The {{o|text}} argument can now be a [[Modding:Common data field types#Translation key|translation key]] to get the text from.
|}
|}


====Deprecated commands====
Switch blocks can be arbitrary combined and nested. For example:
These event commands are deprecated. '''They still work just like before''' (except the ones at the bottom of the table), but if you use the [[#EventValidator|<samp>EventValidator</samp>]] it'll report them as an error.
<syntaxhighlight lang="js">
"Rainy_Night": "${Hello there ||| Hey ${lad^lass^kiddo}$ }$!"
</syntaxhighlight>


===[[Modding:Context tags|Context tag]] changes===
Added new context tags:
{| class="wikitable"
{| class="wikitable"
|-
|-
! event command
! context tag
! migration
! item types
! effect
|-
|-
| <samp>fork</samp><br /><samp>resetVariable</samp><br /><samp>switchEvent</samp>
| <samp>is_galaxy_weapon</samp>
| Use the <samp>choose</samp> or <samp>goto</samp> commands instead. If you used dialogue containing the <samp>%fork</samp> token, it should be removed and replaced with equivalent event commands.
| [[Modding:Weapons|weapons]]
|-
| Marks the tool as a galaxy weapon like the [[Galaxy Hammer|galaxy hammer]] or [[Galaxy Sword|galaxy sword]]. This is set for vanilla scythes through <samp>Data/Weapons</samp>. This affects logic which checks for galaxy weapons (e.g. [[Galaxy Soul|galaxy soul]] enchantments).
| <samp>question forkX</samp>
| Use the <samp>choose</samp> command instead, and replace the event fork with a label.
 
For example, this script:
<pre>
// main event
question fork1 "#I believe in you!#Wow, you're really arrogant."/
fork arrogant/
speak Alex "Thanks, @. I'll remember that."/
...
 
// 'arrogant' event
emote Alex 12/
speak Alex "Hmmph... I think someone's a little jealous.$a"/
</pre>
 
Becomes this script:
<pre>
choose "" "I believe in you!" believe "Wow, you're really arrogant." arrogant/
 
label believe/
speak Alex "Thanks, @. I'll remember that."/
...
 
label arrogant/
emote Alex 12/
speak Alex "Hmmph... I think someone's a little jealous.$a"/
...
</pre>
 
Forks often duplicated the end of the script. In that case, you can have both variants just <samp>goto</samp> the common ending instead.
|-
| <samp>question null</samp>
| Use <samp>choose</samp> with <samp>_</samp> labels instead. (Setting a label argument to <samp>_</samp> means it'll just continue to the next command instead.)
 
For example, this command:
<pre>question null "But what am I going to say to Vincent?#It's best to be honest with kids.#You did the right thing. Kids should have hope."/</pre>
 
Would become this command:
<pre>choose "But what am I going to say to Vincent?" "It's best to be honest with kids." _ "You did the right thing. Kids should have hope." _/</pre>
|-
| <samp>quickQuestion</samp>
| Use the <samp>choose</samp> command instead. The {{t|question}} and {{t|answerX}} have matching <samp>choose</samp> arguments, while the {{t|answerX script}} arguments become labels.
 
For example, this command:
<pre>quickQuestion #I'd like to help#Nah, I'll pass...(break)emote Willy 32\speak Willy "Aye... I thought you would.$h#$b#I'll leave this door unlocked for ya... you can come drop off the materials whenever you like."(break)emote Willy 28\speak Willy "Alright, suit yourself...$s#$b#If you have a change of heart, you can always come back and help out. I'll leave this door unlocked, anyhow."/</pre>
 
Becomes this script:
<pre>
choose "" "I'd like to help" accept "Nah, I'll pass..." refuse/
 
label accept/
emote Willy 32/
speak Willy "Aye... I thought you would.$h#$b#I'll leave this door unlocked for ya... you can come drop off the materials whenever you like."/
goto resume/
 
label refuse/
emote Willy 28/
speak Willy "Alright, suit yourself...$s#$b#If you have a change of heart, you can always come back and help out. I'll leave this door unlocked, anyhow."/
 
label resume/
</pre>
|-
| <samp>cutscene bandfork</samp><br /><samp>elliottBookTalk</samp><br /><samp>question haleyDarkRoom</samp><br /><samp>question shaneCliffs</samp><br /><samp>question shaneLoan</samp>
| These commands are '''deleted''' and will no longer work. They're unlikely to be used by mod events, but see their relevant events for the new equivalents if needed.
|}
|}


====Changed event keys====
Additionally, there is now a data asset for context tags for supporting data (such as for using them in crafting recipes). Located in <samp>Data/ContextTags</samp>, this is a dictionary assets. The key is the context tag, and the value is a data model with the following fields:
Events were generally unified and de-hardcoded in 1.6.16. In particular...
 
<ul>
<li>Several events were previously defined in the game's C# code, where they couldn't be changed by content packs. Most of these were moved into <samp>Data/Events/*</samp> with translations in <samp>Strings/Events</samp>:
{| class="wikitable"
{| class="wikitable"
! event
! new asset name
! new event ID
|-
|-
| [[Giant Stump|forest raccoon]] finished event
! field
| <samp>Data/Events/Forest</samp>
! effect
| <samp>RaccoonFinish</code>
|-
|-
| [[Trash Bear|forest trash bear]] cleanup
| <samp>DisplayName</samp>
| <samp>Data/Events/Forest</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the display name of this context tag. Required when using a context tag as a crafting recipe ingredient.
| <samp>777111</samp>
|-
|-
| [[Ginger Island#Gourmand Frog|island Gourmand crop inspection]]
| <samp>RepresentativeItem</samp>
| <samp>Data/Events/islandFarmCave</samp>
| The qualified item ID for the item representing this context tag. Required when using a context tag as a crafting recipe ingredient.
| <samp>GourmandInspection</samp>
|-
|-
| [[The Summit#Cutscene|summit perfection cutscene]]
| <samp>CustomFields</samp>
| <samp>Data/Events/Summit</samp>
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
| <samp>SummitPerfection</samp>
|}
|-
 
| [[The_Summit#Illegitimate access|summit cheat event]]
===[[Modding:Dialogue|Dialogue]] changes===
| <samp>Data/Events/Summit</samp>
<ul>
| <samp>SummitCheat</samp>
<li>Added a new [[Modding:Dialogue#Special tokens|special token]] in dialogue strings:
|}</li>
<li>Others were moved from non-event data into <samp>Data/Events/*</samp>:
{| class="wikitable"
{| class="wikitable"
! event
! old location
! new asset
! new event ID
|-
|-
| [[Birdie]] quest intro & completed
! token
| <samp>Strings/Locations:IslandSecret_Event_BirdieIntro</samp><br /><samp>Strings/Locations:IslandSecret_Event_BirdieFinished</samp><br /><samp><samp>Strings/Locations:alreadyGotNuts</samp>
! description
| <samp>Data/Events/IslandWest</samp>
| <samp>-888999</samp> (intro)<br /><samp>-666777</samp> (completed)
|-
|-
| [[Ginger Island#Field Office|field office]] intro & completed
| <code>&#124;&#124;&#124;</code>
| <samp>Strings/Locations:IslandFieldOffice_Intro_Event</samp><br /><samp>Strings/Locations:FieldOfficeFinale</samp>
| This is a shortcut for the [[#Switch blocks|randomize switch block]].
| <samp>Data/Events/IslandFieldOffice</samp>
| <samp>FieldOfficeIntro</samp><br /><samp>FieldOfficeDone</samp>
|-
| [[Leo]] intro
| <samp>Strings/Locations:IslandHut_Event_ParrotBoyIntro</samp>
| <samp>Data/Events/IslandHut</samp>
| <samp>LeoIntro</samp>
|-
| [[Meowmere]] event
| <samp>Strings/1_6_Strings:ForestPylonEvent</samp>
| <samp>Data/Events/WizardHouseBasement</samp>
| <samp>ForestPylon</samp>
|-
| [[Mr. Qi#Secrets|Mr. Qi Skull Cavern level 100]]
| <samp>Data/ExtraDialogue:SkullCavern_100_event</samp><br /><samp>Data/ExtraDialogue:SkullCavern_100_event_honorable</samp>
| <samp>Data/Events/SkullCave</samp>
| <samp>SkullCavern100</samp>
|-
| [[Professor Snail]] exits cave
| <samp>Strings/Locations:IslandNorth_Event_SafariManAppear</samp>
| <samp>Data/Events/IslandNorth</samp>
| <samp>ProfSnailIntro</samp>
|}</li>
<li>Other event keys were changed or merged as part of the other event changes:
{| class="wikitable"
|-
! asset
! entry key
! change in 1.6.16
|-
| <samp>Data/Events/AbandonedJojaMart</samp>
| <code>missingBundleComplete</code>
| Event key changed to <code>192393</code> to match the event ID.
|-
| <samp>Data/Events/Farm</samp>
| <code>992559/t 600 1130/n clothFound/o Emily/w sunny</code><br /><code>992559/t 600 1130/n clothFound/O Emily/w sunny</code>
| Merged into a single <code>992559/Time 600 1130/LocalMail clothFound/Weather sunny</code> event.
|-
| <samp>Data/Events/QiNutRoom</samp>
| <code>10040609</code>
| Event key changed to <code>10040609/</code> per the [[#Precondition slash now required for numeric event IDs|precondition change]].
|-
| <samp>Data/Events/SamHouse</samp>
| <code>94/e 93/k 95/t 1800 1950/i 136/y 1</code><br /><code>94/e 93/k 95/t 1800 1950/i 136/y 2</code>
| Merged into a single <code>95/SawEvent 93/!SawEvent 94/Time 1800 1950/HasItem 136</code> event.
|-
| <samp>Data/Events/Town</samp>
| <code>611173/Hn pamHouseUpgrade/o Penny</code>
| Merged into the existing <code>611173/Hn pamHouseUpgrade</code> event.
|}</li>
</ul>


For events that didn't previously have an event ID, their new IDs will be added to the player's seen-events list automatically if needed when the save is loaded.
Delimits an arbitrary number of dialogue variants from which to choose each day. After randomization, any leading or trailing whitespace is trimmed. This randomization is deterministic per day (e.g. reloading the save won't change which one is shown).


====Other event changes====
For example, let's say you did this:
* Moved all vanilla events' on-skip behavior into their event scripts (except the pet adoption logic).
<syntaxhighlight lang="js">
"Rainy_Night": "
    I love rain.$h|||
    I like rain.$h|||
    I adore rain.$h|||
    I hate rain.$s#$b#Just kidding. I love it!$h|||
    I enjoy rain.$h
"
</syntaxhighlight>


===[[Modding:Game state queries|Game state query]] changes===
That would create five variants of the dialogue which each have an equal probability of being selected.
Added new game state queries:
|}</li>
<li>Improved some [[Modding:Dialogue#Special tokens|special tokens]]:
{| class="wikitable"
{| class="wikitable"
|-
|-
! Condition
! token
! effect
! changes
|-
|-
| <samp>IS_DEBRIS_WEATHER</samp><br /><samp>IS_GREEN_RAINING</samp><br /><samp>IS_LIGHTNING</samp><br /><samp>IS_RAINING</samp><br /><samp>IS_SNOWING</samp>
| <code>&#124;&#124;</code>
| Whether the weather in the [[Modding:Game state queries#Target location|given location]] sets the related [[Modding:Weather data#Save files|weather field]]. For example, <samp>IS_RAINING</samp> is true for the <samp>Rain</samp>, <samp>GreenRain</samp>, and <samp>Storm</samp> weathers.
| Whitespace around the token is now ignored, so you can split text into multiple lines:
|-
<syntaxhighlight lang="js">
| <samp>LOCATION_MINE_DIFFICULTY {{t|location}} {{t|min}} {{o|max}}</samp>
"Wed8": "
| Whether the [[Modding:Game state queries#Target location|given location]] is in the [[The Mines|mines]] or [[Skull Cavern]], and its difficulty level is between {{t|min}} and {{o|max}} (default unlimited) inclusively. Difficulty 0 is the default difficulty, and modifiers like the [[Shrine of Challenge]] or some special orders each increase it by one.
    Isn't it expensive, coming to the desert so often like you do?#$e#You must really like to see me, huh? Hmmm... $h||
|-
    *sigh*... I do miss the beautiful flowers of Stardew Valley...$s
| <samp>LOCATION_MINE_LEVEL {{t|location}} {{t|min}} {{o|max}}</samp>
"
| Whether the [[Modding:Game state queries#Target location|given location]] is in the [[The Mines|mines]] or [[Skull Cavern]], and its floor level is between {{t|min}} and {{o|max}} (default unlimited) inclusively. The Skull Cavern implicitly starts at level 121 (e.g. Skull Cavern level 10 is mine level 130).
</syntaxhighlight>
|-
|}</li>
| <samp>PLAYER_HAS_PREVIOUS_CONVERSATION_TOPIC {{t|player}} {{t|id}}+</samp>
<li>Some dialogues were merged or renamed using the new features. The previous dialogue keys are now ignored by the game.
| Whether the [[Modding:Game state queries#Target player|specified player(s)]] have previously had ''any'' of the specified [[Modding:Dialogue#Conversation topics|conversation topics]] active. This doesn't include current topics (unless they're a repeat of a previous one).
|-
| <samp>PLAYER_QUEST_ACTIVE {{t|player}} {{t|id}}+</samp><br /><samp>PLAYER_QUEST_COMPLETE {{t|player}} {{t|id}}+</samp>
| Whether the [[Modding:Game state queries#Target player|specified player(s)]] have ''any'' of the specified quest IDs open (<samp>PLAYER_QUEST_ACTIVE</samp>) or previously completed (<samp>PLAYER_QUEST_COMPLETE</samp>).
|}


===[[Modding:Item queries|Item query]] changes===
Added one new item query:
{| class="wikitable"
{| class="wikitable"
|-
|-
! query
! asset
! effect
! former key
! changes
|-
|-
| <samp>SEASONAL_RACCOON_SEED</samp>
| <samp>Characters/Dialogue/{{t|NPC name}}</samp>
| Get a [[Giant Stump#Note|seasonal raccoon seed]] for the current season.
| <samp><samp>Resort_{{t|number}}</samp><br /><samp>Resort_Bar_{{t|number}}</samp><br /><samp>Resort_Chair_{{t|number}}</samp><br /><samp>Resort_Dance_{{t|number}}</samp><br /><samp>Resort_Shore_{{t|number}}</samp><br /><samp>Resort_Towel_{{t|number}}</samp><br /><samp>Resort_Umbrella_{{t|number}}</samp><br /><samp>Resort_Wander_{{t|number}}</samp>
 
| Merged into their base key (e.g. <samp>Resort_{{t|random}}</samp> into <samp>Resort</samp>) using the new <code>&#124;&#124;&#124;</code> random-variant token.
This sets the stack size to the recommended amount based on the player's luck. When used in item spawn fields, you can set <samp>MinStack</samp> and <samp>MaxStack</samp> to override the stack size.
|}
 
===[[Modding:Item queries#Item spawn fields|Item spawn field]] changes===
<ul>
<li>Added new item spawn fields:
{| class="wikitable"
|-
|-
! field
|rowspan="7"| <samp>Characters/Dialogue/MarriageDialogue</samp><br /><samp>Characters/Dialogue/MarriageDialogue{{t|NPC name}}</samp><br /><samp>Characters/Dialogue/MarriageDialogue{{t|NPC name}}Roommates</samp>
! effect
| <samp>funLeave_{{t|NPC name}}</samp><br /><samp>funReturn_{{t|NPC name}}</samp><br /><samp>jobLeave_{{t|NPC name}}</samp><br /><samp>jobReturn_{{t|NPC name}}</samp><br /><br /><samp>patio_{{t|NPC name}}</samp><br /><samp>spouseRoom_{{t|NPC name}}</samp><br /><br /><samp>spring_{{t|NPC name}}</samp><br /><samp>summer_{{t|NPC name}}</samp><br /><samp>fall_{{t|NPC name}}</samp><br /><samp>winter_{{t|NPC name}}</samp>
| Moved into <samp>MarriageDialogue{{t|NPC name}}</samp> and removed the NPC suffix (like <samp>spouseRoom_{{t|NPC name}}</samp> → <samp>spouseRoom</samp>).
|-
| <samp>Indoor_Day_0</samp><br /><samp>Indoor_Day_1</samp><br /><samp>Indoor_Day_2</samp><br /><samp>Indoor_Day_3</samp><br /><samp>Indoor_Day_4</samp>
| Merged into <samp>Indoor_Day</samp>.
|-
|-
| <samp>Color</samp>
| <samp>Indoor_Night_0</samp><br /><samp>Indoor_Night_1</samp><br /><samp>Indoor_Night_2</samp><br /><samp>Indoor_Night_3</samp><br /><samp>Indoor_Night_4</samp><br /><samp>Indoor_Night_{{t|NPC name}}</samp>
| ''(Optional)'' For item types that support it (e.g. objects and clothes), a [[Modding:Common data field types#Color|tint color]] to apply to the produced item. Default none.
| Merged into <samp>Indoor_Night</samp>.
|-
|-
| <samp>Enchantments</samp>
| <samp>NoBed_0</samp><br /><samp>NoBed_1</samp><br /><samp>NoBed_2</samp><br /><samp>NoBed_3</samp>
| ''(Optional)'' For tools and weapons, the [[Enchantments|enchantment]] IDs to apply (matching their IDs in <samp>Data/Enchantments</samp>). This field applies the normal enchantment rules. Default none.
| Merged into <samp>NoBed</samp>.
 
This is specified as an array, and you can repeat secondary enchantments to boost their level. For example, this applies Vampiric and Attack (level 2):
<syntaxhighlight lang="js">
"Enchantments": [ "Vampiric", "Attack", "Attack" ]
</syntaxhighlight>
|-
|-
| <samp>IsSpecial</samp>
| <samp>Outdoor_0</samp><br /><samp>Outdoor_1</samp><br /><samp>Outdoor_2</samp><br /><samp>Outdoor_3</samp><br /><samp>Outdoor_4</samp><br /><samp>Outdoor_{{t|NPC name}}</samp>
| ''(Optional)'' Whether to mark the produced item as a special permanent item, which can't be destroyed or dropped. Default false.
| Merged into <samp>Outdoor</samp>.
|-
|-
| <samp>ObjectIsQuestItem</samp>
| <samp>Rainy_Day_0</samp><br /><samp>Rainy_Day_1</samp><br /><samp>Rainy_Day_2</samp><br /><samp>Rainy_Day_3</samp><br /><samp>Rainy_Day_4</samp>
| ''(Optional)'' Whether to mark the dropped item as a quest item. This enables special rules like not being able to gift the item, and the item getting auto-recovered when it's lost in some cases. Default false.
| Merged into <samp>Rainy_Day</samp>.
|-
|-
| <samp>TempData</samp>
| <samp>Rainy_Night_0</samp><br /><samp>Rainy_Night_1</samp><br /><samp>Rainy_Night_2</samp><br /><samp>Rainy_Night_3</samp><br /><samp>Rainy_Night_4</samp><br /><samp>Rainy_Night_5</samp><br /><samp>Rainy_Night_{{t|NPC name}}</samp>
| ''(Optional)'' Set temporary item info that's not synchronized in multiplayer or written to the save file. This is somewhat specialized, and does nothing if there's no game logic or C# mod logic which reads it. Default none.
| Merged into <samp>Rainy_Night</samp>.
|}</li>
</ul>


For example, this adds a custom flag:
===Display shops===
<syntaxhighlight lang="js">
In addition to being able to add or change what is sold on Pierre's counter, you can also create your own.
"TempData": {
    "SomeExampleKey": "Example Value"
}
</syntaxhighlight>


A C# code can then check for the field on the dropped items:
Display shops are similar to normal shops, except they show their stocked items in-world. They have a fixed size which is filled from the item pool until it is full (or there is nothing left to add).
<syntaxhighlight lang="c#">
 
if (item.TryGetTempData("SomeExampleKey", out object value))
Display shops are stocked at the beginning of the day, and not restocked until the next day. They are stocked per-farmhand so that they can be different for everyone (such as with backpack upgrades), however a <samp>LimitedStockMode</samp> of <samp>Global</samp> will sync the stock between players, just like a normal shop.
    ...;
 
</syntaxhighlight>
If <samp>LimitedStockMode</samp> is <samp>Player</samp>, then it will be shown before other items, and will not count towards the <samp>ItemCountToSell</samp>. Once a <samp>LimitedStockMode</samp> <samp>Player</samp> item is purchased, it will move to the next not-displayed <samp>LimitedStockMode</samp> <samp>Player</samp> that was stocked, and once those are out of stock it will move on to the synced item stocks.
|}
 
</li>
Display shop items are always purchased one at a time - a higher stack size means it can be bought multiple times.
<li>The <samp>ObjectColor</samp> field is obsolete and replaced by <samp>Color</samp>. Content packs which set it will still work (since the game will pass the value through to <samp>Color</samp> automatically).
 
</ul>
The data asset, located at <samp>Data/DisplayShops</samp>, consists of a string -> model lookup, where...
* The key is the ID of the display shop.
* The value is a model with the fields listed below.


===[[Modding:Maps|Map property]] changes===
<ul>
<li>Added new map properties:
{| class="wikitable"
{| class="wikitable"
|-
|-
! action
! field
! effect
! effect
|-
|-
| <samp>FarmHouseBed {{t|x}} {{t|y}} {{o|item ID}}</samp><br />''(valid in farm or farmhouse)''
!colspan="2"| basic info
| Sets the initial bed to place when creating the farmhouse or cabin. The arguments are:
|-
* {{t|x}} {{t|y}}: the [[Modding:Maps#Tile coordinates|tile position]] at which to place it.
| <samp>OpenCondition</samp>
* {{o|item ID}}: if set, the qualified or unqualified [[Modding:Common data field types#Item ID|item ID]] for the bed furniture to place. This must match a [[Modding:Furniture|furniture item]] with item type <samp>Bed</samp>. Defaults to <code>(F)2048</code> ([[Single Bed|single bed]]).
| ''(Optional)'' A Game State Query for determining if the display shop if is open (that is, if the items shown are purchasable or not). If not specified, it will always be open.
 
If omitted, a [[Single Bed|single bed]] is placed at position (9, 8).
|}</li>
<li>Improved map properties:
{| class="wikitable"
|-
|-
! action
| <samp>ClosedMessage</samp>
! changes
| ''(Optional)'' A Tokenizable String for what message to show if the shop is closed. Defaults to (after token parsing) <samp>"Closed."</samp>.
|-
|-
| <samp>FarmHouseFlooring</samp><br /><samp>FarmHouseFurniture</samp><br /><samp>FarmHouseStarterGift</samp><br /><samp>FarmHouseStarterSeedsPosition</samp><br /><samp>FarmHouseWallpaper</samp>
| <samp>Currency</samp>
| Can now be set on the farmhouse map to override the farm map's equivalent property.
| ''(Optional)'' The currency to use for the price, with the same options as in <samp>Data/Shops</samp>. Defaults to <samp>0</samp> (standard gold).
|-
|-
| <samp>FarmHouseFurniture</samp>
!colspan="2"| cosmetic
| Fixed property only allowing numeric item IDs.
|}</li>
</ul>
 
===[[Modding:Schedule data|Schedule]] changes===
<ul>
<li>Added new schedule keys:
{| class="wikitable"
|-
|-
! syntax
| <samp>PurchaseSound</samp>
! summary
| ''(Optional)'' A sound to play upon making a successful purchase. Defaults to <samp>"purchaseClick"</samp>.
|-
|-
| <samp>roommate_{{t|festival ID}}_{{t|festival day}}</samp><br /><samp>roommate_{{t|festival ID}}</samp><br /><samp>roommate_{{t|season}}_{{t|day of month}}</samp><br /><samp>roommate_{{t|day of week}}</samp><br /><samp>roommateJob</samp>
| <samp>ItemWorldOffset</samp>
| Equivalent to the [[Modding:Schedule data#Marriage schedules|marriage schedules]], but only apply if the NPC is a roommate.
| ''(Optional)'' A Vector2 of how far to move the display item from the tile that has the purchase tile action. For example, Pierre's shop counter has a value of <samp>0 -72</samp> so that the items show on top of the counter. Defaults to <samp>0</samp>.
 
If a roommate NPC has both <samp>roommate*</samp> and <samp>marriage*</samp> schedules, it'll use a <samp>roommate*</samp> schedule if any of them apply. If none apply, it'll default to <samp>marriage*</samp> schedules. You can avoid that by setting the fallback <samp>roommate</samp> schedule key.
|-
|-
| <samp>marriage</samp><br /><samp>roommate</samp>
!colspan="2"| stocked products
| A fallback schedule to use if a more specific schedule doesn't apply. If this is omitted and no other schedule applies, the NPC won't have a schedule that day.
|-
|}</li>
| <samp>ApplyProfitMargins</samp>
</ul>
| ''(Optional)'' Whether or not to apply profit margins by default for items in this shop. Defaults to <samp>null</samp>.
 
|-
===[[Modding:Trigger actions|Trigger action]] changes===
| <samp>PriceModifiers</samp>
<ul>
| ''(Optional)'' Price modifiers to apply to items in this shop. Behaves the same way as <samp>Data/Shops</samp> <samp>PriceModifiers</samp>.
<li>Added new trigger actions:
|-
| <samp>PriceModifierMode</samp>
| ''(Optional)'' Price modifier mod for applying price modifiers to items in this shop. Behaves the same way as <samp>Data/Shops</samp> <samp>PriceModifierMode</samp>.
|-
| <samp>ItemCountToSell</samp>
| ''(Optional)'' The amount of items that can be sold each day.
|-
|valign="top"| <samp>ItemPool</samp>
| ''(Optional)'' The items to use when populating the shop. This list is sorted by <samp>Precedence</samp> before being used, with entries of the same precedence being shuffled together. This list consist of values with these fields:  
{| class="wikitable"
{| class="wikitable"
|-
|-
! action
! field
! effect
! effect
|-
|-
| <samp>CompleteQuest {{t|quest ID}}</samp>
| ''common fields''
| Complete all active quests with this ID in the player's journal.
| See [[Modding:Shops#Format|<samp>Items</samp> for Shops]] for the item fields supported by display shop items.
|}</li>
</ul>


===Other changes===
Notes:
* Added validation for schedule <samp>offset</samp> command in end-of-route animations.
* If set to an [[Modding:Item queries|item query]] which returns multiple items, all of them will be valid choices for the shop.
* Fixed crash when loading a save with missing building interiors.
* Unlike other item spawn fields, <samp>ObjectDisplayName</samp> is supported for any entry (not just Object items).
* Fixed intermittent crash when an item delivery quest for a non-Wizard NPC requests a cooking-type item.
|-
* Fixed <samp>RejectItem_*</samp> dialogue disabling the NPC's normal dialogue after it's shown.
| <samp>DisplayOffset</samp>
* Fixed [[Modding:NPC data|NPC <samp>FlowerDanceCanDance</samp> field]] ignored for non-datable NPCs with no dialogue.
| ''(Optional)'' The amount to offset drawing this item when shown in the display shop. This is useful for non-standard-sized items.
 
==Changes for C# mod authors==
===Instance statics no longer affect mod assemblies===
In [[multiplayer]], split-screen mode works by swapping the values of static fields for each screen (called ''instanced statics''). In previous versions, Stardew Valley would scan all loaded assemblies for static fields marked with <code>[InstancedStatic]</code> attributes except a few ignored assemblies like MonoGame.
 
In Stardew Valley 1.6.16, the game now only does this for the main game assembly to improve performance. If a mod was using <code>[InstancedStatic]</code>, it should use SMAPI's built-in [[Modding:Modder Guide/APIs/Utilities#Per-screen data|per-screen data]] utility instead.
 
===AssetNameUtility===
The new <samp>AssetNameUtility</samp> class has methods for working with [[Modding:Common data field types#Asset name|asset names]]:
 
{| class="wikitable"
|-
|-
! method
| <samp>DisplayScale</samp>
! usage
| ''(Optional)'' How much to scale the item when it is shown. Defaults to <samp>4</samp> (just like most things in the game).
|-
|-
| <samp>Normalize</samp>
| <samp>ItemBlurb</samp>
| A low-level method which normalizes path separators in an [[Modding:Common data field types#Asset name|asset name]]. For example:
| ''(Optional)'' Text to show in a dialogue box before the item prompt appears.
<syntaxhighlight lang="c#">
string assetName = AssetNameUtility.Normalize("Characters/\\/Abigail"); // produces "Characters/Abigail"
</syntaxhighlight>
 
Consider using SMAPI's <samp>PathUtilities.NormalizeAssetName</samp> instead, which is more thorough.
|-
|-
| <samp>TryParseTranslationKey</samp>
| <samp>ItemBlurbSpeaker</samp>
| Parses a [[Modding:Common data field types#Translation key|translation key]] into its component parts. For example:
| ''(Optional)'' The NPC that will "speak" the <samp>ItemBlurb</samp>, if desired.
<syntaxhighlight lang="c#">
|-
if (AssetNameUtility.TryParseTranslationKey("Strings/UI:Confirm", out string assetName, out string fieldKey, out string error))
| <samp>Precedence</samp>
  ...;  // assetName: Strings/UI, fieldKey: Confirm, error: null
| ''(Optional)'' The precedence for this item to be checked, with higher being sooner. Defaults to <samp>0</samp>.
</syntaxhighlight>
|}
 
This doesn't check whether the asset or key exists; see <samp>Game1.content.IsValidTranslationKey</samp> to do that.
|}
|}


===DialogueKeyValidator===
To make the display shop show in world, you need to use a new tile action: <samp>DisplayShop <displayShopId> <itemIndex></samp>, with <samp>displayShopId</samp> being the ID of the entry in <samp>Data/DisplayShops</samp> and <samp>itemIndex</samp> being which index of the stocked items to make available (based on the corresponding <samp>ItemCountToSell</samp> value).
The new <samp>DialogueKeyValidator</samp> class analyses [[Modding:Dialogue|dialogue entries]] to detect dialogue keys which don't match one of the predefined patterns.
 
This is mainly meant to implement unit tests. For example, to validate all dialogue keys in a data asset:
<syntaxhighlight lang="c#">
string assetName = "Characters/Dialogues/Abigail";
var dialogues = Game1.content.Load<Dictionary<string, string>>(assetName);


var validator = new DialogueKeyValidator();
For example, here's how to add a new entry to Pierre's counter:
foreach ((string key, string dialogue) in dialogues)
<syntaxhighlight lang="json">
{
{
     if (!validator.IsKnownFormat(assetName, key))
     "Format": "2.9.0",
         Assert.Fail($"Validation failed for dialogue '{key}': key doesn't match one of the expected patterns.");
    "Changes": [
         {
            "Action": "EditData",
            "Target": "Data/DisplayShops",
            "TargetField": [ "SeedShopCounter", "ItemPool" ],
            "Entries": {
                "{{ModId}}_Weeds": {
                    "ItemId": "(O)0",
                    "Price": 123,
                    "AvailableStock": 3,
                    "ItemBlurb": "wow some weeds. perfect for honey",
                    "ItemBlurbSpeaker": "Penny",
                    "Precedence": -100,
                }
            }
        }
    ]
}
}
</syntaxhighlight>
</syntaxhighlight>


You can optionally extend the valid patterns by setting validator fields like <samp>MarriageDialogueKeyPatterns</samp>.


===EventValidator===
===Enchantment data===
====Overview====
[[Forge#Enchantments|Enchantments]] have been '''partly''' de-hardcoded into a new <samp>Data/Enchantments</samp> data asset. Mods can now easily add new enchantments, including enchantments applied through the [[forge]] using a [[Prismatic Shard|prismatic shard]] or a custom item ID.
The new <samp>EventValidator</samp> class analyses [[Modding:Event data|event scripts]] to detect issues like...
* command names which don't match a registered command or alias;
* command arguments which don't match those expected by the command;
* and custom rule violations based on the <samp>EventValidator.CommandValidators</samp> field (e.g. a default validator checks that <samp>goto</samp> commands match a valid label).


This is mainly meant to implement unit tests for events. For example, to validate all events in a data asset:
However, this logic is still hardcoded:
<syntaxhighlight lang="c#">
* Forging [[Forge#Innate enchantments|innate enchantments]]. The innate enchantments are in data, but the logic to choose which to apply is still hardcoded.
string assetName = "Data/Events/Farm";
* Forging [[diamond]]s into a weapon to fill all its [[Forge#Weapon forging|weapon stat slots]].
var events = Game1.content.Load<Dictionary<string, string>>(assetName);
* Several enchantments' effects when applied (though weapon buff effects are in data).


var validator = new EventValidator();
This consists of a string → model lookup, where...
foreach ((string key, string script) in events)
* The key is the [[Modding:Common data field types#Unique string ID|unique string ID]] for the enchantment.
{
* The value is a model with the fields listed below.
    foreach (var issue in validator.Validator(assetName, key, script))
        Assert.Fail($"Validation failed for event '{key}' > command '{issue.CommandText}': {issue.SuggestedError}.");
}
</syntaxhighlight>


====Command argument validation====
Argument validation is enabled if the command's handler method has an <samp>EventArguments</samp> attribute, which defines the argument pattern using a special syntax. Each command can list multiple patterns, and it'll be considered valid if any of them matches. If the pattern is an empty string, the validator will ensure no arguments are provided.
For example, the default <samp>showFrame</samp> command is defined like this:
<syntaxhighlight lang="c#">
[EventArguments("int", "actor int bool?")]
public static void ShowFrame(Event @event, string[] args, EventContext context)
</syntaxhighlight>
An argument pattern consists of space-delimited ''tokens'', where each token defines the format for an argument. For example, <code>actor int bool?</code> has three tokens representing three arguments: an actor name, a positive integer, and an optional boolean.
These are the tokens recognized by the validator:
{| class="wikitable"
{| class="wikitable"
|-
|-
! token
! field
! meaning
! effect
|-
|-
!colspan="2"| generic argument types
| <samp>DisplayName</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the enchantment's display name, shown in tooltips. This can contain <samp>{0}</samp> for the enchantment level, if applicable.
|-
|-
| <samp>bool</samp>
| <samp>ForgeWith</samp>
| A boolean value (<samp>true</samp> or <samp>false</samp>).
| ''(Optional)'' If set, this enchantment is applied to tools by [[Forge|forging]] an item with this qualified ID into it. Default none, in which case it won't be applicable through the forge.
|-
|-
| <samp>float</samp>
| <samp>AppliesTo</samp>
| A positive number with optional decimal point (like <samp>5</samp> or <samp>0.5</samp>).
| ''(Optional)'' The tools or weapons to which this enchantment can be applied. Defaults to all tools/weapons.
|-
 
| <samp>-float</samp>
This is specified as an array of [[Modding:Context tags|context tag]] queries. The enchantment can be applied if at least one query matches.
| A number with optional decimal point and optional negative sign (like <samp>5</samp>, <samp>-5</samp>, or <samp>-0.5</samp>).
<syntaxhighlight lang="js">
"AppliesTo": [
    "melee_weapon, !is_scythe", // any non-scythe melee weapon
    "hoe, upgrade_level_4"      // any hoe upgraded to iridium or higher
]
</syntaxhighlight>
|-
|-
| <samp>int</samp>
| <samp>EnchantmentSlot</samp>
| A positive integer (like <samp>5</samp>).
| ''(Optional)'' The 'slot' this enchantment goes in. Only one enchantment per slot can normally be applied, except for the "Forge" slot. Default is "Primary".
Valid vanilla types are:
{| class="wikitable"
|-
|-
| <samp>-int</samp>
! type
| An integer with optional negative sign (like <samp>5</samp> or <samp>-5</samp>).
! example
|-  
| <samp>Primary</samp>
| A normal enchantment applied through a prismatic shard.
|-
|-
| <samp>string</samp>
| <samp>Forge</samp>
| A quoted sequence of arbitrary text like <samp>"some words here"</samp>. If the argument has no quotes, this is equivalent to the <samp>word</samp> token.
| A [[Forge#Weapon forging|weapon stat enchantment]] applied through the [[forge]].
|-
|-
| <samp>word</samp>
| <samp>Transforming</samp>
| A simple sequence of letters, numbers, periods, and/or underscores (usually an ID or similar value). While the command will accept quotes, they're redundant and will be rejected by the validator.
| An item transformation enchantment applied through the [[forge]] with [[Galaxy Soul|galaxy souls]].
|-
|-
| <samp>remainder</samp>
| <samp>Innate1</samp> and <samp>Innate2</samp>
| One or more arguments of any type.
| An [[Forge#Innate enchantments|innate enchantment]] applied through the [[forge]] using a [[Dragon Tooth|dragon tooth]].
|}
|-
|-
!colspan="2"| specific string formats
| <samp>IsSecondary</samp>
| ''(Optional)'' Whether this is an [[Forge#Innate enchantments|innate enchantment]] applied through the [[forge]] using a [[Dragon Tooth|dragon tooth]]. Default false.
|-
|-
| <samp>actor</samp>
| <samp>IsVisible</samp>
| An actor name in the event format (like <samp>Abigail</samp> or <samp>Kent?</samp>).
| ''(Optional)'' Whether the enchantment should be shown in the tool/weapon's tooltip. Default true.
|-
|-
| <samp>assetName</samp>
| <samp>MaximumLevel</samp>
| An [[Modding:Common data field types#Asset name|asset name]] like <samp>Data/Achievements</samp>.
| ''(Optional)'' The number of times this enchantment can be applied to the same tool to upgrade the enchantment level (e.g. for [[Forge#Weapon forging|weapon stat enchantments]]). A value of 1 means there's only one enchantment level, so it can't be upgraded by applying the enchantment again. Default 1.
|-
|-
| <samp>direction</samp>
| <samp>EquipmentEffects</samp>
| A [[Modding:Event data#Directions|direction]] which can be specified as either a number (like <samp>0</samp>) or name (like <samp>up</samp>).
| ''(Optional)'' The buffs applied to the weapon when this enchantment is applied.
 
This consists of a list of models with the fields below. You can specify any number of entries; the first one which matches the tool will be applied.
{| class="wikitable"
|-
|-
| <samp>goToLabel</samp>
! field
| An event label (see the <samp>goto</samp> and <samp>label</samp> event commands). This is equivalent to <samp>word</samp>, but is used by <samp>EventValidator</samp> to validate label references.
! effect
|-
|-
| <samp>itemId</samp>
| <samp>Id</samp>
| An [[Modding:Common data field types#Item ID|item ID]] which can be qualified or unqualified (like <samp>(O)MossySoup</samp> or <samp>MossySoup</samp>).
| A [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry.
|-
|-
| <samp>translationKey</samp>
| <samp>MinLevel</samp>
| A [[Modding:Common data field types#Translation key|translation key]] like <samp>Strings/Locations:SomeKey</samp>.
| ''(Optional)'' The minimum enchantment level for which these stats apply. Default 0 (i.e. any level).
|-
|-
!colspan="2"| custom formats
| ''other fields''
| See the <samp>Effects</samp> field [[Modding:Buffs|in <samp>Data/Buffs</samp>]], which is equivalent to this model.
|}
|-
|-
| <samp>'...'</samp>
| <samp>Transformations</samp>
| The literal text or regex pattern to match, like <code>'continue'</code> or <code>'[\w-]+'</code>.
| ''(Optional)'' If <samp>EnchantmentSlot</samp> is <samp>"Transforming"</samp>, this contains all valid transformations for it.
|}


In addition, you can extend tokens with these indicators:
This is a dictionary of qualified item IDs, with the key being the original item, and the value being the transformed item.
* Suffix with <samp>+</samp> for repeating argument of that type. For example, <samp>int+</samp> would allow both <samp>5</samp> and <samp>5 6 7</samp>.
* Suffix with <samp>?</samp> for an optional argument which can be omitted. All tokens after this token must also be optional. (You can have optional repeating arguments like <samp>int+?</samp>.)
* Infix with <samp>|</samp> for a parameter which can be one of multiple types. For example <samp>int|bool</samp> will allow either integer or boolean values.


===Content manager changes===
Transformations to and from items besides weapons are allowed, with some caveats:
The base game's 'content manager' API changed in Stardew Valley 1.6.16. This mainly affects <samp>LanguageCode</samp>, <code>Game1.content</code>, and other content manager fields. This does ''not'' affect mods which only use [[Modding:Modder Guide/APIs/Content|SMAPI's content API]].
* If the source item cannot be enchanted, the maximum level for the enchantment must be 1, or it will not work.
* If the source item and transformed item are different C# types, then all extra item data (such as mod data, enchantments, and tool enchantments) will be lost, since an entirely new item had to be created.
|-
!colspan="2"| advanced
|-
| <samp>CustomFields</samp>
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
|-
| <samp>ClassName</samp>
| ''(Optional, specialized)'' The name of the C# class to construct within the <code>StardewValley.Enchantments</code> namespace. The class must be a subclass of <samp>StardewValley.Enchantments.Enchantment</samp>, and have a constructor with no arguments. For example, given a value of <samp>BottomlessEnchantment</samp>, the game will create <code>StardewValley.Enchantments.BottomlessEnchantment</code> instances.


In particular:
This should usually be omitted, in which case the game will create a generic <samp>Enchantment</samp> instance which uses the data in <samp>Data/Enchantments</samp> for its ID.
<ul>
|}
<li>The game now uses <samp>IContentManager</samp> instead of <samp>LocalizedContentManager</samp> in most places. That includes fields like <code>Game1.content</code>, methods like <code>Game1.content.CreateTemporary()</code>, etc. The new interface also includes full IntelliSense docs.</li>
 
<li>Moved three types:
===[[Modding:Event data|Event]] changes===
Added new event commands:
{| class="wikitable"
{| class="wikitable"
|-
|-
! type
! command
! changes
! description
|-
| <samp>setDrawDepthModifier {{t|npc}} {{t|amountInTiles}}
| Modify the draw depth of {{t|npc}} for this event, by {{t|amountInTiles}}.
|-
|-
| <samp>LocalizedContentManager</samp>
| <samp>setDrawDepthModifier {{t|npc}} reset
| Moved from the <code>StardewValley</code> namespace into <code>StardewValley.ContentManagement</code>.
| Reset the draw depth modifier of {{t|npc}} for this event.
|-
|-
| <samp>LocalizedContentManager.LanguageCode</samp><br /><samp>LocalizedContentManager.LanguageChangedHandler</samp>
| <samp>ForceBreathing {{t|npc}} false
| &#32;
| Prevent {{t|npc}} from showing a breathing animation for this event.
* Moved from the <code>StardewValley</code> namespace into <code>StardewValley.ContentManagement</code>.
* Moved out of the nested type (e.g. change <code>LocalizedContentManager.LanguageCode</code> to just <code>LanguageCode</code> in your mod code).
|}</li>
<li>And changed some <samp>LocalizedContentManager</samp> members:
{| class="wikitable"
|-
|-
! type
| <samp>ForceBreathing {{t|npc}} true {{o|breathPosX}} {{o|breathPosY}} {{o|breathRectX}} {{o|breathRectY}} {{o|breathRectWidth}} {{o|breathRectHeight}}
! member
| Force {{t|npc}} to show a breathing animation for this event. You can optionally override the data used for the breathing rect, with the values following the same behavior as they would if specified in the <samp>Data/Characters</samp> character data.
! changes
|-
| <samp>ForceBreathing {{t|npc}} reset
| Reset the forced breathing modifier of {{t|npc}} for this event.
|-
| <samp>SaveActorState {{t|stateStoreId}} {{t|actor}} {{t|state}}+
| Stores the specified {{t|actor}}'s current {{t|state}}(s) into the {{t|stateStoreId}} actor state store, to be loaded later.
 
Any actor, both NPC and Farmer, can be specified. If <samp>all</samp> is specified, them all actors will have their state saved.
 
Multiple {{t|state}} values can be specified, separated by spaces. Valid {{t|state}} values include:
{| class="wikitable"
|-
! state type
! description
|-
| <samp>all</samp>
| Saves all '''vanilla''' state types for the specified actor.
 
Modded state types are not included here to make it less likely that modded state types will break existing events. For using modded state types in bulk, see the bottom of this table.
|-
|-
|rowspan="8"| <samp>LocalizedContentManager</samp>
| Any state starting with <samp>!</samp>
| <samp>CurrentLanguageCode</samp><br /><samp>CurrentLanguageLatin</samp><br /><samp>CurrentLanguageString</samp><br /><samp>CurrentModLanguage</samp><br /><samp>GetDefaultLanguageCode()</samp><br /><samp>OnLanguageChange</samp><br /><samp>SetModLanguage(…)</samp>
| This will ''remove'' the specified state from the current selection of ones to be saved.
| These are no longer static, so they need to be called through an instance like <samp>Game1.content</samp>. For example, change <code>LocalizedContentManager.GetDefaultLanguageCode()</code> in mod code to <code>Game1.content.GetDefaultLanguageCode()</code>.


Some of these are also renamed (see the next rows).
For example, you could specify <samp>all !movement !animation</samp> to save all state ''except'' the movement state and animation state.
|-
|-
| <samp>CurrentCulture</samp>
| <samp>position</samp>
| Removed (it was unused).
| The current position of the actor.
|-
|-
| <samp>CurrentLanguageCode</samp>
| <samp>movement</samp>
| Renamed to <samp>LanguageCode</samp>.
| The movement state of the actor, including its current speed, <samp>advancedMove</samp> data, and <samp>ignoreCollisions</samp> flag.
|-
|-
| <samp>CurrentLanguageLatin</samp>
| <samp>animation</samp>
| Renamed to <samp>LanguageUsesLatinFont</samp>.
| The animation state of the actor, including its facing direction, <samp>ignoreMovementAnimation</samp> flag, and (for NPCs only) its <samp>ForceBreathing</samp> values.
|-
|-
| <samp>CurrentLanguageString</samp>
| <samp>drawOffset</samp>
| Renamed to <samp>LanguageString</samp>.
| Values previously specified in <samp>drawOffset</samp> and <samp>setDrawDepthModifier</samp>.
|-
|-
| <samp>CurrentModLanguage</samp>
| <samp>name</samp>
| Renamed to <samp>LanguageModData</samp>.
| The NPC's current display name.
|-
|-
| <samp>GetCurrentLanguage()</samp>
| <samp>portrait</samp>
| Removed. Use the <samp>LanguageCode</samp> property instead.
| The NPC's current portrait.
|-
|-
| <samp>OnLanguageChange</samp>
| <samp>sprite</samp>
| Renamed to <samp>OnGlobalLanguageChanged</samp>.
| The NPC's current sprite.
|}</li>
|-
<li>Added a <samp>SourceCodeContentManager</samp> implementation of <samp>IContentManager</samp>. This is meant for internal unit tests, and isn't relevant for mod authors except as an example.</li>
| <samp>shadow</samp>
</ul>
| The NPC's current <samp>hideShadow</samp> value.
|-
| <samp>swimming</samp>
| The NPC's current swimming state.
|-
| Any state ending with <samp>/</samp>
| Specifying a state ending with <samp>/</samp> will result in all state types starting with that string to be added.


===Item changes===
For example, specifying <samp>spacechase0.SpaceCore/</samp> would add ''all'' states that were added by SpaceCore (assuming they were properly namespaced).
* Added <samp>IItemDataDefinition.GetContextTags(itemData)</samp> method, so custom item data definitions can add [[Modding:Context tags|context tags]] from their data if applicable.
* Fixed <code>item.CopyFieldsFrom(other)</code> always setting the stack size for the copy to 1.


===Monster changes===
This also works with "nested namespaces", ex. <samp>spacechase0.SpaceCore/MagicalStuff/</samp> would add all "magical stuff" states added by SpaceCore.
* The [[#Data/Monsters|monster data has been overhauled]].
|}
* The new <samp>monster.Tags</samp> field contains a set of metadata tags about the monster which can be checked in [[#Data/Monsters|<samp>Data/Monsters</samp>]]. It's safe to add new tags to the list for existing monster types.
|-
* The former <samp>monster.objectsToDrop</samp> field (a list of string object IDs) has been replaced by <samp>monster.drops</samp> (an [[Modding:Migrate to Stardew Valley 1.6#Inventory class|item inventory]]).
| <samp>LoadActorStateStore {{t|stateStoreId}}
* Removed <samp>monster.getExtraDropItems()</samp>. Drops should be added in [[#Data/Monsters|<samp>Data/Monsters</samp>]] instead.
| Loads all actor state stored in the {{t|stateStoreId}} actor state store.
|-
| <samp>ClearSavedActorStateStore {{t|stateStoreId}}
| Clears the {{t|stateStoreId}} actor state store.
|}


===Utility fields & methods===
===[[Modding:Fish ponds|Fish pond]] changes===
<ul>
<ul>
<li>1.6.9 adds many new utility methods and fields. For example:
<li>Added new fish pond translation keys:
{| class="wikitable"
{| class="wikitable"
|-
|-
! type
! asset
! member
! key
! usage
! usage
|-
|-
|rowspan="3"| <samp>PassiveFestivalData</samp>
| <samp>Strings/UI</samp>
| <samp>CoversDate(…)</samp>
| <samp>PondQuery_{{t|key}}_{{t|item ID}}</samp><br /><samp>PondQuery_{{t|key}}_{{t|attitude}}</samp>
| Get whether the festival is active on the given date.
| All <samp>PondQuery_*</samp> translation keys can now be suffixed with either the qualified item ID of the fish, or the fish's general attitude based on their <samp>fish_talk_*</samp> [[Modding:Context tags|context tag]].
 
For example, the 'fish are OK' message for an [[anchovy]] pond will be loaded from the first key which exists in this order: <samp>PondQuery_StatusOk_(O)129</samp>, <samp>PondQuery_StatusOk_Rude</samp>, or <samp>PondQuery_StatusOk</samp>.
|}</li>
<li>Merged some fish pond translation keys:
{| class="wikitable"
|-
|-
| <samp>GetFestivalLocations()</samp>
! asset
| Get the locations in which the passive festival happens (based on the <samp>InLocations</samp> or <samp>MapReplacements</samp> fields in [[Modding:Passive Festival data|<samp>Data/PassiveFestivals</samp>]]).
! former key
! changes
|-
|-
| <samp>TryGetLocationReplacement(…)</samp>
| <samp>Strings/UI</samp>
| Get the new location to load instead of a normal one when the passive festival is active. For example, the [[Night Market]] replaces <samp>Beach</samp> with <samp>BeachNightMarket</samp>.
| <samp>PondQuery_Status{{t|status}}{{t|number (0–6)}}</samp><br /><samp>PondQuery_StatusRequestComplete_{{t|fish disposition}}{{t|number (0–2)}}</samp><br /><samp>PondQuery_StatusRequestPending_{{t|fish disposition}}{{t|number (0–2)}}</samp><br />
|-
| Removed the number key suffixes using [[#Switch blocks|switch blocks]] (e.g. merged <samp>PondQuery_StatusOk{{t|number}}</samp> into <samp>PondQuery_StatusOk</samp>).
| <samp>Utility</samp>
|}
| <samp>TryGetPassiveFestivalDataForDayHere(…)</samp>
</li>
| Get the passive festival which occurs on a given date within the given location, if any. This is equivalent to <samp>Utility.TryGetPassiveFestivalDataForDay(…)</samp>, but also checks the given location against the passive festival's <samp>InLocation</samp> or <samp>MapReplacements</samp> field.
<li>[[Coral]] and [[Sea Urchin|Sea urchin]] now have the <samp>fish_talk_coral</samp> [[Modding:Context tags|context tag]] instead of a hardcoded <samp>_Coral</samp> translation key suffixes.</li>
|}</li>
</ul>
</ul>


===Other breaking API changes===
===[[Modding:Item queries|Item query]] changes===
''(This section is meant as a quick reference if you have build errors; there's no need to read through it otherwise.)''
Added one new item query:
 
====Removed or renamed types====
These classes were removed or renamed in 1.6.16:
{| class="wikitable"
{| class="wikitable"
|-
|-
! type
! query
! migration
! effect
|-
|-
| <samp>BaseEnchantment</samp>
| <samp>SEASONAL_RACCOON_SEED</samp>
| Renamed to <samp>Enchantment</samp>.
| Get a [[Giant Stump#Note|seasonal raccoon seed]] for the current season.
 
This sets the stack size to the recommended amount based on the player's luck. When used in item spawn fields, you can set <samp>MinStack</samp> and <samp>MaxStack</samp> to override the stack size.
|}
 
===[[Modding:Item queries#Item spawn fields|Item spawn field]] changes===
<ul>
<li>Added new item spawn fields:
{| class="wikitable"
|-
|-
| <samp>AxeEnchantment</samp><br /><samp>BaseWeaponEnchantment</samp><br /><samp>FishingRodEnchantment</samp><br /><samp>HoeEnchantment</samp><br /><samp>MilkPailEnchantment</samp><br /><samp>PanEnchantment</samp><br /><samp>PickaxeEnchantment</samp><br /><samp>ShearsEnchantment</samp><br /><samp>WateringCanEnchantment</samp>
! field
| Obsolete. Enchantments now [[#Enchantment data|target tools via data]] instead.
! effect
|-
|-
| <samp>Events.DiaryEvent</samp>
| <samp>Enchantments</samp>
| Removed. This was unused.
| ''(Optional)'' For tools and weapons, the [[Enchantments|enchantment]] IDs to apply (matching their IDs in <samp>Data/Enchantments</samp>). This field applies the normal enchantment rules. Default none.
 
This is specified as an array, and you can repeat secondary enchantments to boost their level. For example, this applies Vampiric and Attack (level 2):
<syntaxhighlight lang="js">
"Enchantments": [ "Vampiric", "Attack", "Attack" ]
</syntaxhighlight>
|}
|}
</li>
</ul>


====Other API changes====
===[[Modding:Game state queries|Game state query]] changes===
These class members changed in 1.6.16:
Added game state queries:
 
{| class="wikitable"
{| class="wikitable"
|-
|-
! type
! query
! member
! effect
! migration
|-
| <samp>PLAYER_INVENTORY_SIZE {{t|player}} {{t|minSize}} {{o|maxSize}}</samp>
| Whether ''any one'' of the [[Modding:Game state queries#Target player|specified player(s)]] inventory has at least {{t|minSize}} slots unlocked, and (if specified) less than or equal to {{o|maxSize}} slots unlocked.
|}
 
===<samp>Data/MapPatches</samp> - Dehardcoded map patches===
The base game now has a data-driven conditional map patch system. At the beginning of each day, maps are reloaded, and then these are checked and applied.
 
{| class="wikitable"
|-
! field
! effect
|-
| <samp>OriginalMap</samp>
| The full asset name of the original map(s) that this patch should apply too. Multiple maps can be specified, separate by commas.
|-
| <samp>MapPatch</samp>
| The asset name of the map containing this patch.
|-
| <samp>SourceRect</samp>
| ''(Optional)'' The source rectangle of <samp>MapPatch</samp> to apply. If not specified, the whole map will be used.
|-
| <samp>DestinationPosition</samp>
| The position on <samp>OriginalMap</samp> to place the top left corner of the patch at.
|-
|-
|rowspan="9"| <samp>BaseEnchantment</samp><br /><small>(and its subclasses)</small>
| <samp>MapProperties</samp>
| <samp>hideEnchantmentName</samp>
| ''(Optional)'' Map properties to apply. To remove a property, the value should be null. To append or prepend to a property, use <samp>@MergeInto</samp>.
| Replaced by <samp>EnchantmentManager.HideEnchantmentName</samp>.
|-
|-
| <samp>hideSecondaryEnchantName</samp>
| <samp>Condition</samp>
| Replaced by <samp>EnchantmentManager.HideSecondaryEnchantName</samp>.
| ''(Optional)'' A game state query which indicates whether this entry applies. Default true.
|-
|-
| <samp>GetEnchantmentFromItem(…)</samp>
| <samp>Precedence</samp>
| Replaced by <samp>EnchantmentManager.GetEnchantmentFromItem</samp>.
| ''(Optional)'' The order in which this entry should be checked, where higher precedences will apply over lower precedences.
|-
|-
| <samp>GetAvailableEnchantments()</samp>
!colspan="2"| advanced
| Removed.
|-
<ul>
| <samp>CustomFields</samp>
<li>To check whether any enchantments can be applied to a tool through the [[forge]], use <samp>EnchantmentManager.CanForgeEnchant</samp>.</li>
| ''(Optional)'' The [[Modding:Common data field types#Custom fields|custom fields]] for this entry.
<li>There's no directly equivalent method in 1.6.16, but you can mimic the former logic if needed.
|}
<syntaxhighlight lang="c#">
 
static List<Enchantment> GetAvailableEnchantments()
Previously hard-coded map patches that have been moved over are:
{
{| class="wikitable"
    var dataAsset = DataLoader.Enchantments(Game1.content);
|-
! location
! map change
! ID of entry in <samp>Data/MapPatches</samp>
! additional notes
|-
| [[The Beach]] (including the [[Night Market]])
| The bridge to the right side of the map
| <samp>Beach_Bridge</samp>
| Mostly dehardcoded, but has special logic to apply immediately for everyone rather than at the beginning of the next day.
|-
| [[The Beach]] (including the [[Night Market]])
| [[Carpenter's Shop#Town Shortcuts | Town shortcut]] to the forest
| <samp>Beach_CommunityUpgradeShortcut_ForestEntrance</samp>
| Entirely dehardcoded.


    List<Enchantment> enchantments = [];
Previously, the beach map had the warps for this defined through map properties, even if you haven't unlocked community shortcuts yet. Those warps are now applied through this patch's <samp>MapProperties</samp> and <samp>@MergeInto</samp>.
    foreach ((string id, EnchantmentData data) in dataAsset)
|-
    {
| [[The Beach]] (including the [[Night Market]])
        if (data.ForgeWith == Object.prismaticShardQID)
| [[Carpenter's Shop#Town Shortcuts | Town shortcut]] to the east side of town
            enchantments.Add(EnchantmentManager.CreateEnchantment(dataAsset, id));
| <samp>Beach_CommunityUpgradeShortcut_TownEntrance</samp>
    }
| Entirely dehardcoded.


    return enchantments;
Previously, the beach map had the warps for this defined through map properties, even if you haven't unlocked community shortcuts yet. Those warps are now applied through this patch's <samp>MapProperties</samp> and <samp>@MergeInto</samp>.
}
|-
</syntaxhighlight></li>
| [[The Beach]] (including the [[Night Market]])
</ul>
| The sign leading up to [[SquidFest]]
| <samp>Beach_SquidFest_Sign</samp>
| Entirely dehardcoded
|-
|-
| <samp>GetAvailableEnchantmentsForItem(…)</samp>
| [[The Beach]] (including the [[Night Market]])
| Removed.
| [[SquidFest]]
<ul>
| <samp>Beach_SquidFest</samp>
<li>To check whether any enchantments can be applied to a tool through the [[forge]], use <samp>EnchantmentManager.CanForgeEnchant</samp>.</li>
| Entirely dehardcoded
<li>There's no directly equivalent method in 1.6.16, but you can mimic the former logic if needed.
|-
<syntaxhighlight lang="c#">
| [[The Beach]] (including the [[Night Market]])
static List<Enchantment> GetAvailableEnchantmentsForItem(Item? tool, Item? item)
| Day 2 of [[SquidFest]]'s price increase on the prize sign
{
| <samp>Beach_SquidFest_PriceSignIncrease</samp>
    var dataAsset = DataLoader.Enchantments(Game1.content);
| Entirely dehardcoded
    var contextTags = tool?.GetContextTags();
|-
| colspan="5" | Most existing hard-coded patches have not been moved over to the new system yet, but more will be added over time.
|}


    List<Enchantment> enchantments = [];
===[[Modding:Trigger actions|Trigger action]] changes===
    foreach ((string id, EnchantmentData data) in dataAsset)
Added new trigger actions:
    {
{| class="wikitable"
        if (data.ForgeWith == Object.prismaticShardQID && (contextTags is null || EnchantmentManager.MatchesTags(contextTags, data.AppliesTo)))
|-
            enchantments.Add(EnchantmentManager.CreateEnchantment(dataAsset, id));
! action
    }
! effect
 
    return enchantments;
}
</syntaxhighlight></li>
</ul>
|-
|-
| <samp>GetName()</samp>
| <samp>AddHealth {{t|amount}}</samp>
| Removed. This inconsistently returned an ID, a display name, or <samp>"Unknown Enchantment"</samp> depending on the enchantment type. Use the new <samp>Id</samp> property or the pre-existing <samp>GetDisplayName()</samp> method instead.
| Heals the local player by {{t|amount}} and plays the appropriate sound effect.
|-
|-
| <samp>GetLevel()</samp>
| <samp>IncreaseBackpackSize {{t|amount}}</samp>
| Removed. Use <samp>Level</samp> instead.
| Increase the backpack size of the local player by {{t|amount}}.
|-
|-
| <samp>GetType()</samp>
| <samp>HoldUpItem {{t|itemId}} {{o|message}}</samp>
| This was sometimes to identify enchantments (like <code>enchantment.GetType() == expectedEnchantment.GetType()</code>). That's no longer reliable, since 1.6.16 introduces data-based enchantments which may not have their own C# type. You should use the new <samp>enchantment.Id</samp> property instead.
| Start animation to hold up the specified item above the player's head. If {{o||message}} is specified, it will show that message as well.
|-
|-
| <samp>ResetEnchantments()</samp>
| <samp>MultiplayerGlobalMessage {{t|translationKey}} {{o|arg1}} {{o|arg2}} {{o|arg3}}...</samp>
| Removed. This is no longer needed since it no longer has a cached list of enchantment instances.
| Show a global chat message in multiplayer. The translation key needs to exist in <samp>Strings/UI</samp> and must be prefixed with <samp>Chat_</samp> within that file (meaning you would use <samp>"SomeMessage"</samp> in <samp>MultiplayerGlobalMessage</samp> and <samp>"Chat_SomeMessage"</samp> in <samp>Strings/UI</samp>). Any additional arguments after the translation key (which are parsed as tokenizable strings) will be used as substitution values using the normal notation. (ex. <samp>MultiplayerGlobalMessage "SomeMessage" "meow" "kitty cat"</samp> and <samp>"Chat_SomeMessage": "{1} goes {0}"</samp> would result in the message <samp>"kitty cat goes meow"</samp>)
|-
|-
| <samp>Boots</samp>
| <samp>SetVariable {{t|variableStoreId}} {{t|name}} {{t|value}}</samp>
| <samp>price</samp>
| Sets the value of the variable {{t|name}} in the {{t|variableStoreId}} store to {{t|value}}, if that variable store is writable. (For more on variables, see the relevant section in tokenizable string changes on this page.)
| Removed. This was never used, since boots prices are calculated dynamically.
|-
|-
|rowspan="2"| <samp>Bush</samp>
| <samp>RemoveVariable {{t|variableStoreId}} {{t|name}}</samp>
| <samp>draw(SpriteBatch batch, int yDrawOffset)</samp>
| Removes the variable {{t|name}} in the {{t|variableStoreId}} store, if that variable store is writable. (For more on variables, see the relevant section in tokenizable string changes on this page.)
| Removed. Set the <samp>drawOffset</samp> field and then call <samp>draw(SpriteBatch)</samp> instead.
|}
 
===[[Modding:Tokenizable strings|Tokenizable string]] changes===
====Usable in more places====
Tokenizable strings are now usable in more places.
<ul>
<li>Game state queries</li>
<li>Trigger actions (for <samp>If</samp>, token evaluation is delayed until which value to use is checked)</li>
<li>Event commands
<ul>
<li>Tokens in quotes (ex. a <samp>message "[LocalizedText Strings/Events:MeowKitty]"</samp> command) will be evaluated when that command is run</li>
<li>Any token not in quotes (ex. how wedding events have <samp>[ContextualWeddingCelebrations]</samp> to inject dynamically-constructed commands based on the attendees) will be evaluated when that the event is started.</li>
<li><samp>setSkipActions</samp> delays token evaluation until the actions are actually run, meaning any changes that occur during the event but before the player has actually pressed "skip" will be reflected in the variables used here)</li>
</ul></li>
</ul>
 
Tokens are evaluated immediately, unless otherwise specified.
 
====New tokens====
The following tokens have been added:
{| class="wikitable"
|-
|-
| <samp>yDrawOffset</samp>
! token format
| Replaced by <samp>drawOffset</samp>, which is now public and a <samp>Point</samp>.
! output
|-
|-
| <samp>FishingRod</samp>
| <samp>InputArgument {{t|argumentName}}</samp>
| <samp>lastCatchWasJunk</samp>
| Tokenizable strings can now accept input arguments, depending on where they were called. If the input argument {{t|argumentName}} does not exist, then token evaluation fails.
| Renamed to <samp>lastCatchSkippedMinigame</samp> to more accurately convey what it does.
|}
 
====Token expressions====
Additionally, a new type of tokens now exists (called "expressions"), which are only usable in certain contexts. If one of these tokens is used in a place where it is not allowed, it will fail and say the token was not found. The places where expressions tokens are usable are:
<ul>
<li>Game state queries</li>
<li>Trigger actions</li>
<li>A few specific event commands:
<ul>
<li><samp>action</samp></li>
<li><samp>goto</samp>, specifically for the label(s)</li>
<li><samp>setSkipActions</samp></li>
</ul></li>
</ul>
 
{| class="wikitable"
|-
|-
|rowspan="2"| <samp>Furniture</samp>
! token format
| <samp>armchair</samp><br /><samp>bed</samp><br /><samp>bench</samp><br /><samp>bookcase</samp><br /><samp>chair</samp><br /><samp>couch</samp><br /><samp>decor</samp><br /><samp>dresser</samp><br /><samp>fireplace</samp><br /><samp>lamp</samp><br /><samp>longTable</samp><br /><samp>other</samp><br /><samp>painting</samp><br /><samp>rug</samp><br /><samp>sconce</samp><br /><samp>table</samp><br /><samp>torch</samp><br /><samp>window</samp>
! output
| Removed. Replaced by the <samp>FurnitureType</samp> enum (e.g. <code>Furniture.rug</code> is now <code>FurnitureType.Rug</code>).
|-
|-
| <samp>placementRestrictions</samp>
| <samp>Math Integer {{t|expression}}</samp> <br/>
| Removed. Replaced by <samp>CanPlaceIndoors</samp> and <samp>CanPlaceOutdoors</samp>.
<samp>Math Decimal {{t|expression}}</samp>
| Calculates the given expression as math, using either integers (when <samp>Integer</samp> is specified) or floating point numbers (when <samp>Decimal</samp> is specified).
<ul>
<li>For example, <samp>[Math Integer 3 / 2]</samp> will result in <samp>1</samp>, while <samp>[Math Decimal 3 / 2]</samp> will result in <samp>1.5</samp>. This is because with <samp>Integer</samp> specified, each operation will remove everything after the decimal point before proceeding.</li>
<li>Valid operators include, in order of precedence:
<ul>
<li>Parenthesis (meaning "<samp>(</samp>" and "<samp>)</samp>") can be used to group parts of the epxression to be processed first, similar to how one would expect in a real math expression.</li>
<li><samp>*</samp> (multiplication), <samp>/</samp> (division), and <samp>%</samp> (modulus)</li>
<li><samp>+</samp> (addition) and <samp>-</samp> (subtraction)</li>
</ul></li>
</ul>
|-
|-
|rowspan="2"| <samp>Monster</samp>
| <samp>Comparison {{t|expression}}</samp>
| <samp>getExtraDropItems()</samp>
| Evaluates the given expression, resulting in <samp>TRUE</samp> if the expression is true, and <samp>FALSE</samp> otherwise.
| Removed. Drops should be added to [[#Data/Monsters|<samp>Data/Monsters</samp>]] instead.
<ul>
 
<li>The expression can compare numbers (whether integer or decimal), or strings.</li>
[[Modding:Modder Guide/APIs/Harmony|Harmony patches]] which can't be moved into data can target <samp>Monster.RollForDrops</samp> instead.
<li>Valid operators include, in order of precedence:
<ul>
<li>Parenthesis (meaning "<samp>(</samp>" and "<samp>)</samp>") can be used to group parts of the expression to be processed first, similar to how one would expect in a real math expression.</li>
<li><samp>!</samp> - negation, meaning <samp>[Comparison !TRUE]</samp> becomes <samp>FALSE</samp>, <samp>[Comparison !FALSE]</samp> becomes <samp>TRUE</samp>, and something like <samp>[Comparison !(3 >= 5)]</samp> becomes <samp>TRUE</samp></li>
<li><samp>&lt;</samp> (less than), <samp>&lt;=</samp> (less than or equal to), <samp>&lg;</samp> (greater than), <samp>&gt;=</samp> (greater than or equal to)</li>
<li><samp>==</samp> (equal to) and <samp>!=</samp> (not equal to)</li>
<li><samp>&&</samp> ("and"), meaning <samp>[Comparison 2 > 1 && 3 == 3]</samp> becomes <samp>FALSE</samp></li>
<li><samp>||</samp> ("or"), meaning <samp>[Comparison 2 > 1 || 3 == 3]</samp> becomes <samp>TRUE</samp></li>
<li>(For those who know what "logical comparison short circuiting" is, please be aware that that is currently not implemented.)</li>
</ul></li>
</ul>
|-
|-
| <samp>objectsToDrop</samp>
| <samp>If {{t|condition}} {{t|trueValue}} {{o|falseValue}}</samp>
| Removed. Replaced by <samp>drops</samp>; see [[#Monster changes|''monster changes'']] and [[#Data/Monsters|''<samp>Data/Monsters</samp>'']].
| If {{t|condition}} evalautes to <samp>TRUE</samp>, then {{t|trueValue}} is evaluated and returned. If {{t|condition}} evalutes to <samp>FALSE</samp>, then {{o|falseValue}} is evaluated and returned (if it was specified - otherwise, nothing is returned).
|-
|-
|rowspan="3"| <samp>NPCDialogueResponse</samp><br /><samp>Response</samp>
| <samp>GameStateQuery {{t|gsq}}</samp>
| <samp>id</samp><br /><samp>friendshipChange</samp><br /><samp>extraArgument</samp><br /><samp>hotkey</samp><br /><samp>responseText</samp>
| Evaluates the given game state query, allowing GSQ usage inside <samp>[If]</samp>.
| Fields changed to get-only properties.
|-
|-
| <samp>responseKey</samp>
| <samp>VariableExists {{t|variableStore}} {{t|variableName}}</samp>
| &#32;
| Evaluates to <samp>TRUE</samp> if {{t|variableStore}} has a variable named {{t|variableName}}, and <samp>FALSE</samp> otherwise. (For more on variable stores, see later section.)
* Field changed to get-only property.
* Previously <samp>NPCDialogueResponse</samp> stored the NPC's reaction dialogue key in this field. You should now use <samp>npcReactionKey</samp> for that instead.
|-
|-
| <samp>SetHotKey(…)</samp>
| <samp>GetVariable {{t|variableStore}} {{t|variableName}}</samp>
| Removed. Set the hotkey through the constructor instead.
| Evaluates to the value of {{t|variableName}} in the variable store {{t|variableStore}}. If the variable does not exist, evaluation of the tokenizable string will fail. (For more on variable stores, see later section.)
|-
|-
| <samp>Tool</samp>
| <samp>GetVariableWithDefault {{t|variableStore}} {{t|variableName}} {{t|defaultValue}}</samp>
| <samp>GetEnchantmentLevel&lt;T&gt;()</samp><br /><samp>GetEnchantmentOfType&lt;T&gt;()</samp><br /><samp>hasEnchantmentOfType&lt;T&gt;()</samp>
| Evaluates to the value of {{t|variableName}} in the variable store {{t|variableStore}}. If the variable does not exist, {{t|defaultValue}} will be returned instead. (For more on variable stores, see later section.)
| Removed. Replaced by <samp>GetEnchantmentLevel(id)</samp>, <samp>GetEnchantment(id)</samp>, and <samp>HasEnchantment(id)</samp> respectively. All vanilla enchantments have a constant for the ID like <samp>EnchantmentIds.GalaxySoul</samp>.
|}
|}


===Other changes===
====Variable stores====
* Added <samp>PlatformAchievementIds</samp> and <samp>QuestIds</samp> constants.
Variables stores are a set of named variables stored in a particular location. The current available locations used as variable stores are:
* Added <samp>event.floorSprites</samp> field for temporary animated sprites that should be drawn on the ground (e.g. under NPC shadows).
{| class="wikitable"
* The game now uses forward slashes in all asset names (like <samp>Maps/Town</samp> instead of <samp>Maps\Town</samp>). This shouldn't affect most mods, since SMAPI already converted all asset names to forward slashes.
* Removed broken <samp>Lantern</samp> tool, <samp>Raft</samp> tool, and their related logic.
* Fixed <code>Event.TryGetEventCommandHandler</code> not loading commands if it's called before any other methods.
* Fixed machine auto-load leaving empty slots in chests when taking a secondary ingredient.
* Fixed issue where placing a storage furniture (e.g. a dresser or fish tank) on a table would discard any items inside it.
 
==Name translation changes for wiki maintainers==
Some in-game item and monster names were retranslated in some languages for clarity or correctness.
 
This list is mostly provided to help wiki maintainers update pages, so it doesn't include names which only changed capitalization, changed <code>'</code> (straight apostrophe) to <code>’</code> (curly) in French, or aren't visible to vanilla players (like mine rocks).
 
===Objects===
; Hungarian
: {| class="wikitable"
|-
|-
! item
! variable store ID
! old name
! description
! new name
|-
|-
| [[Artichoke Dip]]
| <samp>Global</samp>
| ''Articsóka mártás''
| A variable store attached to the save itself.
| ''Articsókamártás''
<ul>
<li>Any player can read and write from this.</li>
<li>This variable store will be saved into the save file at the end of the day.</li>
</ul>
|-
|-
| [[Blackberry Cobbler]]
| <samp>Player/{{t|playerSpecifier}}</samp>
| ''Szeder kosár''
| A variable store attached to a particular player.
| ''Szedres kosárka''
<ul>
<li>{{t|playerSpecifier}} uses the same format as [[Modding:Game state queries#Target player|game state query target players]], except specifiers that work for check multiple players (such as <samp>Any</samp> or <samp>All</samp>) may not be used.</li>
<li>Any player can read from this, however only the owning player can write to their variable store.</li>
<li>If a player is disconnected, their variables are saved, and will be resynced when they reconnect.</li>
<li>This variable store will be saved into the save file at the end of the day.</li>
</ul>
|-
|-
| [[Bone Mill]]
| <samp>Local</samp>
| ''Csontőrlő''
| A variable store attached to a "calling context". Generally, this means it will always be reset between uses unless specifically kept, such as in the following contexts:
| ''Csontdaráló''
<ul>
|-
<li>Events - A variable set in the <samp>Local</samp> variable store using the <samp>action</samp> event command will be usable later during that event.</li>
| [[Chocolate Cake]]
<li><samp>Data/TriggerActions</samp> - When a trigger action has multiple actions to run, all actions will be using the same <samp>Local</samp> variable store, meaning earlier trigger actions can save data for use by later trigger actions in the same sequence.</samp></li>
| ''Csokis torta''
</ul>
| ''Csokitorta''
|-
| [[Cranberry Candy]]
| ''Vörös áfonyás cukorka''
| ''Vörös áfonyás üdítő''
|-
| [[Geode Crusher]]
| ''Geóda zúzó''
| ''Geódazúzó''
|-
| [[Maple Syrup]]
| ''Juharfaszirup''
| ''Juharszirup''
|-
| [[Tea Sapling]]
| ''Tea csemete''
| ''Teacsemete''
|-
| [[Woodcutter's Weekly]]
| ''Favágok hetilapja''
| ''Favágók hetilapja''
|}
|}


; Russian
===Debug command changes===
: {| class="wikitable"
This only details some debug command changes - mainly, ones that might be useful for mod authors.
 
{| class="wikitable"
|-
|-
! item
! command
! old name
! changes
! new name
|-
|-
|rowspan="71" valign="top"| [[Aged Roe]] (flavored)
| <samp>/tokens</samp>
| ''Вяленая икра (Альбакор)''<!--Albacore-->
| A new required parameter has been introduced as the first argument, {{t|type}}. If {{t|type}} is <samp>Text</samp> the string will be evaluated using non-expression tokens. If {{t|type}} is <samp>Expression</samp>, expression tokens will be allowed as well.
| ''Вяленая икра альбакора''
|-
|-
| ''Вяленая икра (Анчоус)''<!--Anchovy-->
| <samp>/runmacro</samp>
| ''Вяленая икра анчоуса''
| Commented lines are now allowed - if <samp>--</samp> is the beginning of a line, it will be ignored.
|-
|-
| ''Вяленая икра (Морской черт)''<!--Angler-->
| <samp>/debugaction</samp> (new)
| ''Вяленая икра Морского черта''
| A new command for trying out tokenizable string input arguments, tokenizable string local variables, and trigger actions using them. This command maintains its own set of input arguments and a local variable store, which can be manipulated using the subcommands.
{| class="wikitable"
|-
|-
| ''Вяленая икра (Рыба-капля)''<!--Blobfish-->
! subcommand
| ''Вяленая икра рыбы-капли''
! effect
|-
|-
| ''Вяленая икра (Голубой дискус)''<!--Blue Discus-->
| <samp>/debugaction argument {{t|name}} {{t|value}}</samp>
| ''Вяленая икра голубого дискуса''
| Sets the input argument {{t|name}} to {{t|value}}, which can be later used in <samp>/debugaction run</samp> and <samp>/debugaction evaluate</samp>.
|-
|-
| ''Вяленая икра (Лещ)''<!--Bream-->
| <samp>/debugaction evaluate {{t|expression}}</samp>
| ''Вяленая икра леща''
| Evaluates {{t|expression}} as a tokenizable string, using input arguments and local variables previously set from this command.
|-
|-
| ''Вяленая икра (Сомик)''<!--Bullhead-->
| <samp>/debugaction run {{t|action}}</samp>
| ''Вяленая икра сомика''
| Runs {{t|action}} as a trigger action, using input arguments and local variables previously set from this command.
|-
|-
| ''Вяленая икра (Карп)''<!--Carp-->
| <samp>/debugaction clear</samp>
| ''Вяленая икра карпа''
| Clears all previously set input arguments and local variables for <samp>/debugaction</samp>.
|}
Some examples of using this command alongside <samp>/runmacro</samp>, at least at the time of writing, can be found here: https://gist.github.com/spacechase0/3ca7b2e195619a17ef9039c894cc60e4
|-
|-
| ''Вяленая икра (Сом)''<!--Catfish-->
| <samp>/enchant {{t|enchantmentId}} {{o|level}}</samp> (new)
| ''Вяленая икра сома''
| Enchant the currently held item with the {{t|enchantmentId}} enchantment at level {{o|level}} (or 1 if not specified).
|-
|}
| ''Вяленая икра (Голавль)''<!--Chub-->
 
| ''Вяленая икра голавля''
==Changes for C# mod authors==
|-
===DialogueKeyValidator===
| ''Вяленая икра (Гребешок)''<!--Clam-->
The new <samp>DialogueKeyValidator</samp> class analyses [[Modding:Dialogue|dialogue entries]] to detect dialogue keys which don't match one of the predefined patterns.
| ''Вяленая икра гребешка''
 
|-
This is mainly meant to implement unit tests. For example, to validate all dialogue keys in a data asset:
| ''Вяленая икра (Сердцевидка)''<!--Cockle-->
<syntaxhighlight lang="c#">
| ''Вяленая икра сердцевидки''
string assetName = "Characters/Dialogues/Abigail";
|-
var dialogues = Game1.content.Load<Dictionary<string, string>>(assetName);
| ''Вяленая икра (Краб)''<!--Crab-->
 
| ''Вяленая икра краба''
var validator = new DialogueKeyValidator();
|-
foreach ((string key, string dialogue) in dialogues)
| ''Вяленая икра (Рак)''<!--Crayfish-->
{
| ''Вяленая икра рака''
    if (!validator.IsKnownFormat(assetName, key))
|-
        Assert.Fail($"Validation failed for dialogue '{key}': key doesn't match one of the expected patterns.");
| ''Вяленая икра (Багрянник)''<!--Crimsonfish-->
}
| ''Вяленая икра Багрянника''
</syntaxhighlight>
|-
 
| ''Вяленая икра (Дорада)''<!--Dorado-->
You can optionally extend the valid patterns by setting validator fields like <samp>MarriageDialogueKeyPatterns</samp>.
| ''Вяленая икра дорады''
 
|-
===Monster changes===
| ''Вяленая икра (Угорь)''<!--Eel-->
* The [[#Data/Monsters|monster data has been overhauled]].
| ''Вяленая икра угря''
* The new <samp>monster.Tags</samp> field contains a set of metadata tags about the monster which can be checked in [[#Data/Monsters|<samp>Data/Monsters</samp>]]. It's safe to add new tags to the list for existing monster types.
|-
* The former <samp>monster.objectsToDrop</samp> field (a list of string object IDs) has been replaced by <samp>monster.drops</samp> (an [[Modding:Migrate to Stardew Valley 1.6#Inventory class|item inventory]]).
| ''Вяленая икра (Камбала)''<!--Flounder-->
* Removed <samp>monster.getExtraDropItems()</samp>. Drops should be added in [[#Data/Monsters|<samp>Data/Monsters</samp>]] instead.
| ''Вяленая икра камбалы''
 
|-
===Recipe changes===
| ''Вяленая икра (Пятнистый криворот)''<!--Ghostfish-->
As part of the change for recipes using data models, <samp>Farmer.recipesCooked</samp> and <samp>Farmer.cookedRecipe(itemId)</samp> now use qualified item IDs instead of unqualified object item IDs.
| ''Вяленая икра пятнистого криворота''
 
|-
===<samp>SpecialItem</samp> deprecation===
| ''Вяленая икра (Ледорыб)''<!--Glacierfish-->
<samp>SpecialItem</samp> is now deprecated, and is only kept for save compatibility. All existing uses of it have been migrated to use <samp>Object</samp> instead, with the following new objects being available:
| ''Вяленая икра Ледорыба''
<ul>
|-
<li><samp>(O)BackpackUpgrade1</samp></li>
| ''Вяленая икра (Ледорыб-младший)''<!--Glacierfish Jr.-->
<li><samp>(O)BackpackUpgrade2</samp></li>
| ''Вяленая икра Ледорыба-младшего''
<li><samp>(O)ClubCard</samp></li>
|-
<li><samp>(O)SpecialCharm</samp></li>
| ''Вяленая икра (Бычок)''<!--Goby-->
<li><samp>(O)SkullKey</samp></li>
| ''Вяленая икра бычка''
<li><samp>(O)MagnifyingGlass</samp></li>
|-
<li><samp>(O)DarkTalisman</samp></li>
| ''Вяленая икра (Палтус)''<!--Halibut-->
<li><samp>(O)MagicInk</samp></li>
| ''Вяленая икра палтуса''
</ul>
|-
 
| ''Вяленая икра (Сельдь)''<!--Herring-->
===Tokenizable string changes===
| ''Вяленая икра сельди''
Tokenizable string parsing and evaluation has been separated into two separate stages. As a result, several places that use them now cache the parsed version (which is called <samp>ParsedStringSegment</samp>).
|-
 
| ''Вяленая икра (Ледопип)''<!--Ice Pip-->
Any custom trigger actions, tokenizable string tokens, or event commands that want to delay tokenizable string evaluation so they can handle it themself (such as for only evaluating portions that should be used based on a condition) can attach the <samp>[DelayArgumentTokenEvaluation]</samp> attribute to their handler method. This will prevent the arguments from being evaluated before they reach your handler. (However, the handlers themselves currently still use <samp>string[]</samp> as their arguments, so this could be slightly off depending on how quotes were used.)
| ''Вяленая икра ледопипа''
 
|-
<samp>TokenParser.ParseText(string text, Random random, TokenParserDelegate customParser, Farmer player)</samp> is now deprecated, and <samp>TokenParser.EvaluateText(string text, TokenParserContext context)</samp> should be used instead.
| ''Вяленая икра (Большеротый окунь)''<!--Largemouth Bass-->
 
| ''Вяленая икра большеротого окуня''
===Tool changes===
|-
The following were added to <samp>Tool</samp>:
| ''Вяленая икра (Лавовый угорь)''<!--Lava Eel-->
{| class="wikitable"
| ''Вяленая икра лавового угря''
|-
| ''Вяленая икра (Легенда)''<!--Legend-->
| ''Вяленая икра Легенды''
|-
|-
| ''Вяленая икра (Легенда II)''<!--Legend II-->
! member
| ''Вяленая икра Легенды II''
! effect
|-
|-
| ''Вяленая икра (Змеезуб)''<!--Lingcod-->
| <samp>virtual bool DrawEvenWhenNotUsing</samp>
| ''Вяленая икра змеезуба''
| If <samp>true</samp>, <samp>Game1.drawTool</samp> (and therefore <samp>Tool.draw</samp>) will be called even if the <samp>Farmer.UsingTool</samp> is false. Default <samp>false</samp>.
|-
|-
| ''Вяленая икра (Крылатка)''<!--Lionfish-->
| <samp>virtual bool DrawNormalToolFrames</samp>
| ''Вяленая икра крылатки''
| If <samp>false</samp>, <samp>Game1.drawTool</samp> will not draw the normal "swinging" tool frames. Default <samp>true</samp>.
|-
|-
| ''Вяленая икра (Омар)''<!--Lobster-->
| <samp>virtual bool DoAction(GameLocation location, Farmer who)</samp>
| ''Вяленая икра омара''
| Called when the player does a right click rather than a left click. Return <samp>true</samp> if the tool is doing something, and <samp>false</samp> otherwise.
|-
|}
| ''Вяленая икра (Полуночный карп)''<!--Midnight Carp-->
 
| ''Вяленая икра полуночного карпа''
===Netfield changes===
|-
The following changes must now all be registered with <samp>ProtocolSummary</samp> before usage:
| ''Вяленая икра (Ночной кальмар)''<!--Midnight Squid-->
<ul>
| ''Вяленая икра ночного кальмара''
<li>Additional net fields</li>
|-
<li>Additional net types</li>
| ''Вяленая икра (Мисс Морской черт)''<!--Ms. Angler-->
<li>Subclasses of any synced type</li>
| ''Вяленая икра Мисс Морской черт''
</ul>
|-
If this is not done, an exception will be thrown when adding netfields, or setting values of unknown types.
| ''Вяленая икра (Мидия)''<!--Mussel-->
 
| ''Вяленая икра мидий''
Instead of manually registering with <samp>ProtocolSummary</samp> or manually adding net fields using a harmony patch, everything should be registered through a new SMAPI API (coming soon) which will handle these details for you. This will ensure that if mods load in a different order on one player's computer compared to other connected players, it will not break anything.
|-
 
| ''Вяленая икра (Карп-мутант)''<!--Mutant Carp-->
If a farmhand's <samp>ProtocolSummary</samp> does not match the host's, they will get a protocol mismatch error upon connecting (rather than "No cabins available", or other obscure and unclear issues).
| ''Вяленая икра Карпа-мутанта''
 
===C# Event changes===
C# mods can add new actor state to work with the new <samp>SaveActorState</samp>/etc. commands (previously documented in [[#Event changes|event changes]] above).
 
On <samp>Event</samp> there exists a new static function, <samp>RegisterActorStateType</samp>, which accepts the name of the new actor state type (which you should namespace with your mod ID, ex. <samp>spacechase0.SpaceCore/SomeCustomActorState</samp>), a delegate for saving the state, and a delegate for loading the state. Each delegate receives the <samp>Event</samp> instance, the relevant actor (which could be an <samp>NPC</samp> or a <samp>Farmer</samp>), and a delegate for performing the save and load to the proper place.
 
===Enchantment changes===
Besides the data-driven changes mentioned previously, <samp>Enchantment</samp>s can now <i>theoretically</i> be put on non-<samp>Tool</samp>s more easily. Most of the enchantment code has been moved from <samp>Tool</samp> to <samp>Item</samp>, and relevant functions accepting instances of the former now accept the latter. <samp>Item</samp> itself does not <i>store</i> enchantments though, so a custom type that supports enchantments will need to implement a virtual property so that they are properly stored.
 
There are also new hooks for enchantments to run: before/after taking damage, entering/leaving a location, and an update each tick.
 
===Other breaking API changes===
''(This section is meant as a quick reference if you have build errors; there's no need to read through it otherwise.)''
 
====Removed or renamed types====
These classes renamed in 1.7:
{| class="wikitable"
|-
|-
| ''Вяленая икра (Осьминог)''<!--Octopus-->
! type
| ''Вяленая икра осьминога''
! migration
|-
|-
| ''Вяленая икра (Устрица)''<!--Oyster-->
| <samp>BaseEnchantment</samp>
| ''Вяленая икра устриц''
| Renamed to <samp>Enchantment</samp>.
|-
|-
| ''Вяленая икра (Окунь)''<!--Perch-->
| <samp>AxeEnchantment</samp><br /><samp>BaseWeaponEnchantment</samp><br /><samp>FishingRodEnchantment</samp><br /><samp>HoeEnchantment</samp><br /><samp>MilkPailEnchantment</samp><br /><samp>PanEnchantment</samp><br /><samp>PickaxeEnchantment</samp><br /><samp>ShearsEnchantment</samp><br /><samp>WateringCanEnchantment</samp>
| ''Вяленая икра окуня''
| Obsolete. Enchantments now [[#Enchantment data|target tools via data]] instead.
|}
 
====Other API changes====
These class members changed in 1.7:
 
{| class="wikitable"
|-
|-
| ''Вяленая икра (Литорина)''<!--Periwinkle-->
! type
| ''Вяленая икра литорин''
! member
! migration
|-
|-
| ''Вяленая икра (Щука)''<!--Pike-->
|rowspan="9"| <samp>BaseEnchantment</samp><br /><small>(and its subclasses)</small>
| ''Вяленая икра щуки''
| <samp>hideEnchantmentName</samp>
|-
| Replaced by <samp>EnchantmentManager.HideEnchantmentName</samp>.
| ''Вяленая икра (Иглобрюх)''<!--Pufferfish-->
| ''Вяленая икра иглобрюха''
|-
|-
| ''Вяленая икра (Радиоактивный карп)''<!--Radioactive Carp-->
| <samp>hideSecondaryEnchantName</samp>
| ''Вяленая икра Радиоактивного карпа''
| Replaced by <samp>EnchantmentManager.HideSecondaryEnchantName</samp>.
|-
|-
| ''Вяленая икра (Радужная форель)''<!--Rainbow Trout-->
| <samp>GetEnchantmentFromItem(…)</samp>
| ''Вяленая икра радужной форели''
| Replaced by <samp>EnchantmentManager.GetEnchantmentFromItem</samp>.
|-
|-
| ''Вяленая икра (Барабулька)''<!--Red Mullet-->
| <samp>GetAvailableEnchantments()</samp>
| ''Вяленая икра барабульки''
| Removed.
<ul>
<li>To check whether any enchantments can be applied to a tool through the [[forge]], use <samp>EnchantmentManager.CanForgeEnchant</samp>.</li>
<li>There's no directly equivalent method in 1.7, but you can mimic the former logic if needed.
<syntaxhighlight lang="c#">
static List<Enchantment> GetAvailableEnchantments()
{
    var dataAsset = DataLoader.Enchantments(Game1.content);
 
    List<Enchantment> enchantments = [];
    foreach ((string id, EnchantmentData data) in dataAsset)
    {
        if (data.ForgeWith == Object.prismaticShardQID)
            enchantments.Add(EnchantmentManager.CreateEnchantment(dataAsset, id));
    }
 
    return enchantments;
}
</syntaxhighlight></li>
</ul>
|-
|-
| ''Вяленая икра (Берикс)''<!--Red Snapper-->
| <samp>GetAvailableEnchantmentsForItem(…)</samp>
| ''Вяленая икра берикса''
| Removed.
<ul>
<li>To check whether any enchantments can be applied to a tool through the [[forge]], use <samp>EnchantmentManager.CanForgeEnchant</samp>.</li>
<li>There's no directly equivalent method in 1.7, but you can mimic the former logic if needed.
<syntaxhighlight lang="c#">
static List<Enchantment> GetAvailableEnchantmentsForItem(Item? tool, Item? item)
{
    var dataAsset = DataLoader.Enchantments(Game1.content);
    var contextTags = tool?.GetContextTags();
 
    List<Enchantment> enchantments = [];
    foreach ((string id, EnchantmentData data) in dataAsset)
    {
        if (data.ForgeWith == Object.prismaticShardQID && (contextTags is null || EnchantmentManager.MatchesTags(contextTags, data.AppliesTo)))
            enchantments.Add(EnchantmentManager.CreateEnchantment(dataAsset, id));
    }
 
    return enchantments;
}
</syntaxhighlight></li>
</ul>
|-
|-
| ''Вяленая икра (Лосось)''<!--Salmon-->
| <samp>GetName()</samp>
| ''Вяленая икра лосося''
| Removed. This inconsistently returned an ID, a display name, or <samp>"Unknown Enchantment"</samp> depending on the enchantment type. Use the new <samp>Id</samp> property or the pre-existing <samp>GetDisplayName()</samp> method instead.
|-
|-
| ''Вяленая икра (Песковник)''<!--Sandfish-->
| <samp>GetLevel()</samp>
| ''Вяленая икра песковника''
| Removed. Use <samp>Level</samp> instead.
|-
|-
| ''Вяленая икра (Сардина)''<!--Sardine-->
| <samp>GetType()</samp>
| ''Вяленая икра сардины''
| This was sometimes to identify enchantments (like <code>enchantment.GetType() == expectedEnchantment.GetType()</code>). That's no longer reliable, since 1.7 introduces data-based enchantments which may not have their own C# type. You should use the new <samp>enchantment.Id</samp> property instead.
|-
|-
| ''Вяленая икра (Скорпионовый карп)''<!--Scorpion Carp-->
| <samp>ResetEnchantments()</samp>
| ''Вяленая икра скорпионового карпа''
| Removed. This is no longer needed since it no longer has a cached list of enchantment instances.
|-
|-
| ''Вяленая икра (Морской огурец)''<!--Sea Cucumber-->
|rowspan="2"| <samp>Furniture</samp>
| ''Вяленая икра морского огурца''
| <samp>armchair</samp><br /><samp>bed</samp><br /><samp>bench</samp><br /><samp>bookcase</samp><br /><samp>chair</samp><br /><samp>couch</samp><br /><samp>decor</samp><br /><samp>dresser</samp><br /><samp>fireplace</samp><br /><samp>lamp</samp><br /><samp>longTable</samp><br /><samp>other</samp><br /><samp>painting</samp><br /><samp>rug</samp><br /><samp>sconce</samp><br /><samp>table</samp><br /><samp>torch</samp><br /><samp>window</samp>
| Removed. Replaced by the <samp>FurnitureType</samp> enum (e.g. <code>Furniture.rug</code> is now <code>FurnitureType.Rug</code>).
|-
|-
| ''Вяленая икра (Морской еж)''<!--Sea Urchin-->
| <samp>placementRestrictions</samp>
| ''Вяленая икра морского ежа''
| Removed. Replaced by <samp>CanPlaceIndoors</samp> and <samp>CanPlaceOutdoors</samp>.
|-
|-
| ''Вяленая икра (Шэд)''<!--Shad-->
| <samp>GreenSlime</samp>
| ''Вяленая икра шэда''
| <samp>prismatic</samp>
| Removed. Replaced by <samp>IsPrismatic</samp>, which is just a wrapper around the monster tags field.
|-
|-
| ''Вяленая икра (Креветка)''<!--Shrimp-->
|rowspan="2"| <samp>Monster</samp>
| ''Вяленая икра креветок''
| <samp>getExtraDropItems()</samp>
| Removed. Drops should be added to [[#Data/Monsters|<samp>Data/Monsters</samp>]] instead.
 
[[Modding:Modder Guide/APIs/Harmony|Harmony patches]] which can't be moved into data can target <samp>Monster.RollForDrops</samp> instead.
|-
|-
| ''Вяленая икра (Слаймджек)''<!--Slimejack-->
| <samp>objectsToDrop</samp>
| ''Вяленая икра слаймджека''
| Removed. Replaced by <samp>drops</samp>; see [[#Monster changes|''monster changes'']] and [[#Data/Monsters|''<samp>Data/Monsters</samp>'']].
|-
|-
| ''Вяленая икра (Малоротый окунь)''<!--Smallmouth Bass-->
| <samp>Tool</samp>
| ''Вяленая икра малоротого окуня''
| <samp>GetEnchantmentLevel&lt;T&gt;()</samp><br /><samp>GetEnchantmentOfType&lt;T&gt;()</samp><br /><samp>hasEnchantmentOfType&lt;T&gt;()</samp>
| Removed. Replaced by <samp>GetEnchantmentLevel(id)</samp>, <samp>GetEnchantment(id)</samp>, and <samp>HasEnchantment(id)</samp> respectively. All vanilla enchantments have a constant for the ID like <samp>EnchantmentIds.GalaxySoul</samp>.
|-
|-
| ''Вяленая икра (Улитка)''<!--Snail-->
| <samp>Tool</samp>
| ''Вяленая икра улиток''
|
<samp>ClearEnchantments()</samp><br />
<samp>GetMaxForges()</samp><br />
<samp>CanAddEnchantment(…)</samp><br />
<samp>CopyEnchantments(…)</samp><br />
<samp>GetTotalForgeLevels(…)</samp><br />
<samp>AddEnchantment(…)</samp><br />
<samp>RemoveEnchantment(…)</samp><br />
<samp>CanForge(…)</samp><br />
<samp>HasEnchantment(…)</samp><br />
<samp>GetEnchantment(…)</samp><br />
<samp>GetEnchantmentLevel(…)</samp><br />
<samp>Forge(…)</samp>
| Removed. Enchantment functions have been moved to <samp>Item</samp> to make it easier for non-<samp>Tool</samp>s to support enchantments.
 
NOTE: <samp>Tool</samp> is still the only type that can actually hold enchantments, since nothing else has the appropriate fields to hold them.
|-
|-
| ''Вяленая икра (Малек Багрянника)''<!--Son of Crimsonfish-->
| <samp>Tool</samp>
| ''Вяленая икра Малька Багрянника''
| <samp>drawTooltip&lt;T&gt;(…)</samp><br /><samp>getExtraSpaceNeededForTooltipSpecialIcons&lt;T&gt;(…)</samp><br /><samp>getDescriptionWidth&lt;T&gt;()</samp><br /><samp>AddEquipmentEffects&lt;T&gt;()</samp>
| Removed. These were only overrides of <samp>Item</samp> functions that only handled enchantments, which is now handled in <samp>Item</samp> itself.
|-
|-
| ''Вяленая икра (Жуть-рыба)''<!--Spook Fish-->
| <samp>AnimatedSprite</samp>
| ''Вяленая икра жуть-рыбы''
| <samp>Clone</samp>
| No longer virtual. It now uses a similar model that `Item` does, with a virtual `CloneNew` for creating the instance and a virtual `CloneInto` for populating it.
|-
|-
| ''Вяленая икра (Кальмар)''<!--Squid-->
| <samp>FarmerSprite</samp>
| ''Вяленая икра кальмара''
| <samp>Clone</samp>
| Now returns a properly cloned <samp>FarmerSprite</samp>, rather than a semi-broken <samp>AnimatedSprite</samp> based on itself.
|-
|-
| ''Вяленая икра (Скат)''<!--Stingray-->
| <samp>Farmer</samp>
| ''Вяленая икра ската''
| <samp>takeDamage&lt;T&gt;(…)</samp>
| The last argument has been changed from <samp>Monster</samp> to <samp>object</samp>, to support the ability to detect damage from non-<samp>Monster</samp> sources. An example of this is <samp>BasicProjectile</samp>, which previously passed in <samp>null</samp> for that parameter.
|-
|-
| ''Вяленая икра (Рыба-камень)''<!--Stonefish-->
| <samp>Ring</samp>
| ''Вяленая икра рыбы-камня''
|
<samp>onNewLocation(…)</samp> <br />
<samp>onLeaveLocation(…)</samp>
| These are now overrides of a function on <samp>Item</samp>. All equipped items will now have this function called.
|-
|-
| ''Вяленая икра (Солнечник)''<!--Sunfish-->
| <samp>Ring</samp>
| ''Вяленая икра солнечника''
|
<samp>update(…)</samp>
| This now a function called <samp>updateWhenEquipped</samp>, and is an override of the same virtual function in <samp>Item</samp>. All equipped items will have this function called.
|-
|-
| ''Вяленая икра (Чудо-огурец)''<!--Super Cucumber-->
| <samp>GameLocation</samp>
| ''Вяленая икра чудо-огурца''
| <samp>getFish(…)</samp>
|-
| A new non-optional parameter has been added: <samp>out Action onCatch</samp>.
| ''Вяленая икра (Тигровая форель)''<!--Tiger Trout-->
 
| ''Вяленая икра тигровой форели''
Implementations of this method should no longer make changes to the world and instead be purely predictive. Any actual changes (ex. fish ponds changing how many fish it has, ginger island locations marking a golden walnut as collected, ...)  should be within <samp>onCatch</samp>, which will be called when the item is successfully reeled in.
|-
|}
| ''Вяленая икра (Тиляпия)''<!--Tilapia-->
 
| ''Вяленая икра тиляпии''
==Name translation changes for wiki maintainers==
|-
Some in-game item and monster names were retranslated in some languages for clarity or correctness.
| ''Вяленая икра (Тунец)''<!--Tuna-->
 
| ''Вяленая икра тунца''
This list is mostly provided to help wiki maintainers update pages, so it doesn't include names which only changed capitalization, changed <code>'</code> (straight apostrophe) to <code>’</code> (curly) in French, or aren't visible to vanilla players (like mine rocks).
 
''None yet.''
 
==XNB impact==
<!--
 
Updated up to 1.7 alpha 2025-09-13.
 
-->
===Overview===
This section provides a summary of the XNB files which changed in Stardew Valley 1.7. This doesn't include new files (since they won't impact existing mods) or text changes in non-English files.
 
[[Modding:Using XNB mods|XNB mods]] are disproportionately affected, since...
# they replace the entire file;
# they're loaded through the MonoGame content pipeline which is less tolerant of format changes;
# they don't benefit from the compatibility rewrites [[Modding:Content Patcher|Content Patcher]] provides for its content packs.
 
Content Patcher packs are typically unaffected (and Content Patcher will try to rewrite content packs automatically). However if a content pack replaces an entire asset instead of editing, it's more likely to be affected like an XNB mod.
 
===Changed assets===
Compatibility is broadly grouped into four categories:
* "'''✘ broken'''": mods will remove new content or significant changes, or the mod's intended changes will no longer work. Effects may range from display bugs to crashes, depending how the game uses that specific content.
* "✘ will remove changes": mods will remove minor changes in 1.7 (e.g. typo fixes).
* "✓ mostly unaffected": mods will only be affected if they edit specific entries or fields.
* Blank: no expected impact for the vast majority of mods.
 
{| class="wikitable"
|-
|-
| ''Вяленая икра (Лосось пустоты)''<!--Void Salmon-->
!rowspan="2"| content asset
| ''Вяленая икра лосося пустоты''
!rowspan="2"| changes in 1.7
!colspan="2"| compatibility for pre-1.7 mods
|-
|-
| ''Вяленая икра (Желтый судак)''<!--Walleye-->
! XNB mods
| ''Вяленая икра желтого судака''
! Content Patcher packs
|-
|-
| ''Вяленая икра (Лесоплюх)''<!--Woodskip-->
| <samp>Characters/Dialogue/Abigail</samp>
| ''Вяленая икра лесоплюха''
| &#32;
* [[#Dialogue changes|Merged resort dialogue keys]].
* Fixed invalid dialogue keys.
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Bait]]
| <samp>Characters/Dialogue/Alex</samp><br /><samp>Characters/Dialogue/Clint</samp>
| ''Приманка''
| [[#Dialogue changes|Merged resort dialogue keys]].
| ''Наживка''
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Basic Retaining Soil]]
| <samp>Characters/Dialogue/Dwarf</samp>
| ''Обычная влагосохраняющая почва''
| Fixed invalid dialogue keys.
| ''Обычный аквагрунт''
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Deluxe Retaining Soil]]
| <samp>Characters/Dialogue/Elliott</samp>
| ''Влагосохраняющая почва Делюкс''
| &#32;
| ''Аквагрунт Делюкс''
* [[#Dialogue changes|Merged resort dialogue keys]].
* Fixed invalid dialogue key.
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Dried Fruit]] (flavored)
| <samp>Characters/Dialogue/Evelyn</samp>
| ''Сушеная морошка''<!--Salmonberry-->
| Fixed invalid dialogue key.
| ''Сушеная малина''
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Jellies and Pickles|Jelly]] (flavored)
| <samp>Characters/Dialogue/Haley</samp>
| ''Джем из морошки''<!--Salmonberry-->
| [[#Dialogue changes|Merged resort dialogue keys]].
| ''Малиновый джем''
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Juice]] (flavored)
| <samp>Characters/Dialogue/Harvey</samp>
| ''Сок сквоша''<!--Summer Squash-->
| Fixed invalid dialogue key.
| ''Кабачковый сок''
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Magic Bait]]
| <samp>Characters/Dialogue/Jodi</samp>
| ''Волшебная приманка''
| Fixed invalid dialogue key.
| ''Волшебная наживка''
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Quality Fertilizer]]
| <samp>Characters/Dialogue/Leah</samp>
| ''Высококачественное удобрение''
| [[#Dialogue changes|Merged resort dialogue keys]].
| ''Улучшенное удобрение''
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Quality Retaining Soil]]
| <samp>Characters/Dialogue/Lewis</samp>
| ''Высококачественная влагосохраняющая почва''
| Fixed invalid dialogue key.
| ''Улучшенный аквагрунт''
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| [[Quality Sprinkler]]
| <samp>Characters/Dialogue/MarriageDialogue</samp><br /><samp>Characters/Dialogue/MarriageDialogue*</samp>
| ''Высококачественный спринклер''
| &#32;
| ''Улучшенный спринклер''
* [[#Dialogue changes|Merged some dialogue keys]].
* [[#Dialogue changes|Merged some keys from the base asset into NPC-specific assets]].
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
|rowspan="72" valign="top"| [[Roe]] (flavored)
| <samp>Characters/Dialogue/Maru</samp><br /><samp>Characters/Dialogue/Penny</samp><br /><samp>Characters/Dialogue/Sam</samp>
| ''Икра (Альбакор)''<!--Albacore-->
| [[#Dialogue changes|Merged resort dialogue keys]].
| ''Икра альбакора''
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| ''Икра (Анчоус)''<!--Anchovy-->
| <samp>Characters/Dialogue/Sebastian</samp>
| ''Икра анчоуса''
| &#32;
* [[#Dialogue changes|Merged resort dialogue keys]].
* Fixed invalid dialogue key.
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| ''Икра (Морской черт)''<!--Angler-->
| <samp>Data/Boots</samp>
| ''Икра Морского черта''
| [[#Data/Boots|Overhauled format]].
| '''✘ broken'''
| '''✘ broken'''<br /><small>(until Content Patcher adds runtime migrations)</small>
|-
|-
| ''Икра (Рыба-капля)''<!--Blobfish-->
| <samp>Data/Buffs</samp>
| ''Икра рыбы-капли''
| [[#Data/Buffs|Added new data field to data model]].
| '''✘ broken'''
|
|-
|-
| ''Икра (Голубой дискус)''<!--Blue Discus-->
| <samp>Data/Buildings</samp><br /><samp>Data/Characters</samp>
| ''Икра голубого дискуса''
| [[#Item spawn field changes|Added new item spawn field]].
| '''✘ broken'''
|
|-
|-
| ''Икра (Лещ)''<!--Bream-->
| <samp>Data/FishPondData</samp><br /><samp>Data/FruitTrees</samp>
| ''Икра леща''
| [[#Item spawn field changes|Added new item spawn field]].
| '''✘ broken'''
|
|-
|-
| ''Икра (Сомик)''<!--Bullhead-->
| <samp>Data/Furniture</samp>
| ''Икра сомика''
| [[#Data/Furniture|Overhauled format]].
| '''✘ broken'''
| '''✘ broken'''<br /><small>(until Content Patcher adds runtime migrations)</small>
|-
|-
| ''Икра (Карп)''<!--Carp-->
| <samp>Data/GarbageCans</samp><br /><samp>Data/GiantCrops</samp>
| ''Икра карпа''
| [[#Item spawn field changes|Added new item spawn field]].
| '''✘ broken'''
|
|-
|-
| ''Икра (Сом)''<!--Catfish-->
| <samp>Data/Hats</samp>
| ''Икра сома''
| [[#Data/Hats|Overhauled format]].
| '''✘ broken'''
| '''✘ broken'''<br /><small>(until Content Patcher adds runtime migrations)</small>
|-
|-
| ''Икра (Голавль)''<!--Chub-->
| <samp>Data/Locations</samp>
| ''Икра голавля''
| [[#Item spawn field changes|Added new item spawn field]].
| '''✘ broken'''
|
|-
|-
| ''Икра (Гребешок)''<!--Clam-->
| <samp>Data/Machines</samp>
| ''Икра гребешка''
| [[#Item spawn field changes|Added new item spawn field]].
| '''✘ broken'''
|
|-
|-
| ''Икра (Сердцевидка)''<!--Cockle-->
| <samp>Data/Monsters</samp>
| ''Икра сердцевидки''
| [[#Data/Monsters|Overhauled format]].
| '''✘ broken'''
| '''✘ broken'''<br /><small>(until Content Patcher adds runtime migrations)</small>
|-
|-
| ''Икра (Краб)''<!--Crab-->
| <samp>Data/Movies</samp>
| ''Икра краба''
| [[#Item spawn field changes|Added new item spawn field]].
| '''✘ broken'''
|
|-
|-
| ''Икра (Рак)''<!--Crayfish-->
| <samp>Data/Objects</samp>
| ''Икра рака''
| &#32;
* [[#Data/Objects|Added new data field to data model]] and [[#Item spawn field changes|new item spawn fields]].
* Added <samp>fish_talk_coral</samp> [[#New context tags|context tag]] for [[coral]] and [[Sea Urchin|sea urchin]].
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| ''Икра (Багрянник)''<!--Crimsonfish-->
| <samp>Data/Pets</samp><br /><samp>Data/Shops</samp>
| ''Икра Багрянника''
| [[#Item spawn field changes|Added new item spawn field]].
| '''✘ broken'''
|
|-
|-
| ''Икра (Дорада)''<!--Dorado-->
| <samp>Data/Weapons</samp>
| ''Икра дорады''
| &#32;
* [[#Item spawn field changes|Added new item spawn field]].
* Added <samp>is_galaxy_weapon</samp> [[#New context tags|context tag]] for galaxy weapons.
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| ''Икра (Угорь)''<!--Eel-->
| <samp>Data/WildTrees</samp>
| ''Икра угря''
| [[#Item spawn field changes|Added new item spawn field]].
| '''✘ broken'''
|
|-
|-
| ''Икра (Камбала)''<!--Flounder-->
| <samp>Strings/1_6_Strings</samp>
| ''Икра камбалы''
| Moved some translations into <samp>Strings/EnchanmentNames</samp> and <samp>Strings/Furniture</samp>.
|
|
|-
|-
| ''Икра (Пятнистый криворот)''<!--Ghostfish-->
| <samp>Strings/EnchantmentNames</samp>
| ''Икра пятнистого криворота''
| &#32;
* Added translations moved from <samp>Strings/1_6_Strings</samp>.
* Renamed two keys (<samp>Auto-Hook</samp> → <samp.AutoHook</samp>, <samp>Bug Killer</samp> → <samp>BugKiller</samp>).
| '''✘ broken'''
| ✓ mostly unaffected
|-
|-
| ''Икра (Ледорыб)''<!--Glacierfish-->
| <samp>Strings/Furniture</samp>
| ''Икра Ледорыба''
| Added translations for catalogue descriptions (moved from <samp>Strings/1_6_Strings</samp>).
| '''✘ broken'''
|
|-
|-
| ''Икра (Ледорыб-младший)''<!--Glacierfish Jr.-->
| <samp>Strings/Objects</samp>
| ''Икра Ледорыба-младшего''
| Moved catalogue descriptions into <samp>Strings/Furniture</samp>.
| ✓ mostly unaffected
| ✓ mostly unaffected
|-
|-
| ''Икра (Бычок)''<!--Goby-->
| <samp>Strings/UI</samp>
| ''Икра бычка''
| [[#Fish pond changes|Merged some fish pond translation keys]].
| '''✘ broken'''
| ✓ mostly unaffected
|}
 
===Removed or moved translation keys===
These [[Modding:Common data field types#Translation key|translation keys]] were moved or removed in 1.6.16. (For changes to the content, see ''[[#Changed assets|changed assets]]'' above.)
 
{| class="wikitable"
|-
|-
| ''Икра (Палтус)''<!--Halibut-->
! asset
| ''Икра палтуса''
! key
|-
! changes
| ''Икра (Сельдь)''<!--Herring-->
| ''Икра сельди''
|-
| ''Икра (Ледопип)''<!--Ice Pip-->
| ''Икра ледопипа''
|-
| ''Икра (Большеротый окунь)''<!--Largemouth Bass-->
| ''Икра большеротого окуня''
|-
| ''Икра (Лавовый угорь)''<!--Lava Eel-->
| ''Икра лавового угря''
|-
| ''Икра (Легенда)''<!--Legend-->
| ''Икра Легенды''
|-
| ''Икра (Легенда II)''<!--Legend II-->
| ''Икра Легенды II''
|-
| ''Икра (Змеезуб)''<!--Lingcod-->
| ''Икра змеезуба''
|-
| ''Икра (Крылатка)''<!--Lionfish-->
| ''Икра крылатки''
|-
| ''Икра (Омар)''<!--Lobster-->
| ''Икра омара''
|-
| ''Икра (Полуночный карп)''<!--Midnight Carp-->
| ''Икра полуночного карпа''
|-
| ''Икра (Ночной кальмар)''<!--Midnight Squid-->
| ''Икра ночного кальмара''
|-
| ''Икра (Мисс Морской черт)''<!--Ms. Angler-->
| ''Икра Мисс Морской черт''
|-
| ''Икра (Мидия)''<!--Mussel-->
| ''Икра мидий''
|-
| ''Икра (Карп-мутант)''<!--Mutant Carp-->
| ''Икра Карпа-мутанта''
|-
| ''Икра (Осьминог)''<!--Octopus-->
| ''Икра осьминога''
|-
| ''Икра (Устрица)''<!--Oyster-->
| ''Икра устриц''
|-
| ''Икра (Окунь)''<!--Perch-->
| ''Икра окуня''
|-
| ''Икра (Литорина)''<!--Periwinkle-->
| ''Икра литорин''
|-
| ''Икра (Щука)''<!--Pike-->
| ''Икра щуки''
|-
| ''Икра (Иглобрюх)''<!--Pufferfish-->
| ''Икра иглобрюха''
|-
| ''Икра (Радиоактивный карп)''<!--Radioactive Carp-->
| ''Икра Радиоактивного карпа''
|-
| ''Икра (Радужная форель)''<!--Rainbow Trout-->
| ''Икра радужной форели''
|-
| ''Икра (Барабулька)''<!--Red Mullet-->
| ''Икра барабульки''
|-
| ''Икра (Берикс)''<!--Red Snapper-->
| ''Икра берикса''
|-
| ''Икра (Лосось)''<!--Salmon-->
| ''Икра лосося''
|-
| ''Икра (Песковник)''<!--Sandfish-->
| ''Икра песковника''
|-
| ''Икра (Сардина)''<!--Sardine-->
| ''Икра сардины''
|-
| ''Икра (Скорпионовый карп)''<!--Scorpion Carp-->
| ''Икра скорпионового карпа''
|-
| ''Икра (Морской огурец)''<!--Sea Cucumber-->
| ''Икра морского огурца''
|-
| ''Икра (Морской еж)''<!--Sea Urchin-->
| ''Икра морского ежа''
|-
| ''Икра (Шэд)''<!--Shad-->
| ''Икра шэда''
|-
| ''Икра (Креветка)''<!--Shrimp-->
| ''Икра креветок''
|-
| ''Икра (Слаймджек)''<!--Slimejack-->
| ''Икра слаймджека''
|-
| ''Икра (Малоротый окунь)''<!--Smallmouth Bass-->
| ''Икра малоротого окуня''
|-
| ''Икра (Улитка)''<!--Snail-->
| ''Икра улиток''
|-
| ''Икра (Малек Багрянника)''<!--Son of Crimsonfish-->
| ''Икра Малька Багрянника''
|-
| ''Икра (Жуть-рыба)''<!--Spook Fish-->
| ''Икра жуть-рыбы''
|-
| ''Икра (Кальмар)''<!--Squid-->
| ''Икра кальмара''
|-
| ''Икра (Скат)''<!--Stingray-->
| ''Икра ската''
|-
| ''Икра (Рыба-камень)''<!--Stonefish-->
| ''Икра рыбы-камня''
|-
| ''Икра (Осетр)''<!--Sturgeon-->
| ''Икра осетра''
|-
| ''Икра (Солнечник)''<!--Sunfish-->
| ''Икра солнечника''
|-
| ''Икра (Чудо-огурец)''<!--Super Cucumber-->
| ''Икра чудо-огурца''
|-
| ''Икра (Тигровая форель)''<!--Tiger Trout-->
| ''Икра тигровой форели''
|-
| ''Икра (Тиляпия)''<!--Tilapia-->
| ''Икра тиляпии''
|-
| ''Икра (Тунец)''<!--Tuna-->
| ''Икра тунца''
|-
| ''Икра (Лосось пустоты)''<!--Void Salmon-->
| ''Икра лосося пустоты''
|-
| ''Икра (Желтый судак)''<!--Walleye-->
| ''Икра желтого судака''
|-
| ''Икра (Лесоплюх)''<!--Woodskip-->
| ''Икра лесоплюха''
|-
| [[Salmonberry]]
| ''Морошка''
| ''Малина''
|-
| [[Summer Squash Seeds]]
| ''Семена сквоша''
| ''Семена кабачка''
|-
| [[Summer Squash]]
| ''Сквош''
| ''Кабачок''
|-
|rowspan="71" valign="top"| [[Targeted Bait]]
| ''Наживка: Альбакор''<!--Albacore-->
| ''Наживка на альбакора''
|-
| ''Наживка: Анчоус''<!--Anchovy-->
| ''Наживка на анчоуса''
|-
| ''Наживка: Морской черт''<!--Angler-->
| ''Наживка на Морского черта''
|-
| ''Наживка: Рыба-капля''<!--Blobfish-->
| ''Наживка на рыбу-каплю''
|-
| ''Наживка: Голубой дискус''<!--Blue Discus-->
| ''Наживка на голубого дискуса''
|-
| ''Наживка: Лещ''<!--Bream-->
| ''Наживка на леща''
|-
| ''Наживка: Сомик''<!--Bullhead-->
| ''Наживка на сомика''
|-
| ''Наживка: Карп''<!--Carp-->
| ''Наживка на карпа''
|-
| ''Наживка: Сом''<!--Catfish-->
| ''Наживка на сома''
|-
| ''Наживка: Голавль''<!--Chub-->
| ''Наживка на голавля''
|-
| ''Наживка: Гребешок''<!--Clam-->
| ''Приманка для гребешков''
|-
| ''Наживка: Сердцевидка''<!--Cockle-->
| ''Приманка для сердцевидок''
|-
| ''Наживка: Краб''<!--Crab-->
| ''Приманка для крабов''
|-
| ''Наживка: Рак''<!--Crayfish-->
| ''Приманка для раков''
|-
| ''Наживка: Багрянник''<!--Crimsonfish-->
| ''Наживка на Багрянника''
|-
| ''Наживка: Дорада''<!--Dorado-->
| ''Наживка на дораду''
|-
| ''Наживка: Угорь''<!--Eel-->
| ''Наживка на угря''
|-
| ''Наживка: Камбала''<!--Flounder-->
| ''Наживка на камбалу''
|-
| ''Наживка: Пятнистый криворот''<!--Ghostfish-->
| ''Наживка на пятнистого криворота''
|-
| ''Наживка: Ледорыб''<!--Glacierfish-->
| ''Наживка на Ледорыба''
|-
| ''Наживка: Ледорыб-младший''<!--Glacierfish Jr.-->
| ''Наживка на Ледорыба-младшего''
|-
| ''Наживка: Бычок''<!--Goby-->
| ''Наживка на бычка''
|-
| ''Наживка: Палтус''<!--Halibut-->
| ''Наживка на палтуса''
|-
| ''Наживка: Сельдь''<!--Herring-->
| ''Наживка на сельдь''
|-
| ''Наживка: Ледопип''<!--Ice Pip-->
| ''Наживка на ледопипа''
|-
| ''Наживка: Большеротый окунь''<!--Largemouth Bass-->
| ''Наживка на большеротого окуня''
|-
| ''Наживка: Лавовый угорь''<!--Lava Eel-->
| ''Наживка на лавового угря''
|-
| ''Наживка: Легенда''<!--Legend-->
| ''Наживка на Легенду''
|-
| ''Наживка: Легенда II''<!--Legend II-->
| ''Наживка на Легенду II''
|-
| ''Наживка: Змеезуб''<!--Lingcod-->
| ''Наживка на змеезуба''
|-
| ''Наживка: Крылатка''<!--Lionfish-->
| ''Наживка на крылатку''
|-
| ''Наживка: Омар''<!--Lobster-->
| ''Приманка для омаров''
|-
| ''Наживка: Полуночный карп''<!--Midnight Carp-->
| ''Наживка на полуночного карпа''
|-
| ''Наживка: Ночной кальмар''<!--Midnight Squid-->
| ''Наживка на ночного кальмара''
|-
| ''Наживка: Мисс Морской черт''<!--Ms. Angler-->
| ''Наживка на Мисс Морской черт''
|-
| ''Наживка: Мидия''<!--Mussel-->
| ''Приманка для мидий''
|-
| ''Наживка: Карп-мутант''<!--Mutant Carp-->
| ''Наживка на Карпа-мутанта''
|-
| ''Наживка: Осьминог''<!--Octopus-->
| ''Наживка на осьминога''
|-
| ''Наживка: Устрица''<!--Oyster-->
| ''Приманка для устриц''
|-
| ''Наживка: Окунь''<!--Perch-->
| ''Наживка на окуня''
|-
| ''Наживка: Литорина''<!--Periwinkle-->
| ''Приманка для литорин''
|-
| ''Наживка: Щука''<!--Pike-->
| ''Наживка на щуку''
|-
| ''Наживка: Иглобрюх''<!--Pufferfish-->
| ''Наживка на иглобрюха''
|-
| ''Наживка: Радиоактивный карп''<!--Radioactive Carp-->
| ''Наживка на Радиоактивного карпа''
|-
| ''Наживка: Радужная форель''<!--Rainbow Trout-->
| ''Наживка на радужную форель''
|-
| ''Наживка: Барабулька''<!--Red Mullet-->
| ''Наживка на барабульку''
|-
| ''Наживка: Берикс''<!--Red Snapper-->
| ''Наживка на берикса''
|-
| ''Наживка: Лосось''<!--Salmon-->
| ''Наживка на лосося''
|-
| ''Наживка: Песковник''<!--Sandfish-->
| ''Наживка на песковника''
|-
| ''Наживка: Сардина''<!--Sardine-->
| ''Наживка на сардину''
|-
| ''Наживка: Скорпионовый карп''<!--Scorpion Carp-->
| ''Наживка на скорпионового карпа''
|-
| ''Наживка: Морской огурец''<!--Sea Cucumber-->
| ''Наживка на морского огурца''
|-
| ''Наживка: Шэд''<!--Shad-->
| ''Наживка на шэда''
|-
| ''Наживка: Креветка''<!--Shrimp-->
| ''Приманка для креветок''
|-
| ''Наживка: Слаймджек''<!--Slimejack-->
| ''Наживка на слаймджека''
|-
| ''Наживка: Малоротый окунь''<!--Smallmouth Bass-->
| ''Наживка на малоротого окуня''
|-
| ''Наживка: Улитка''<!--Snail-->
| ''Приманка для улиток''
|-
| ''Наживка: Малек Багрянника''<!--Son of Crimsonfish-->
| ''Наживка на Малька Багрянника''
|-
| ''Наживка: Жуть-рыба''<!--Spook Fish-->
| ''Наживка на жуть-рыбу''
|-
| ''Наживка: Кальмар''<!--Squid-->
| ''Наживка на кальмара''
|-
| ''Наживка: Скат''<!--Stingray-->
| ''Наживка на ската''
|-
| ''Наживка: Рыба-камень''<!--Stonefish-->
| ''Наживка на рыбу-камень''
|-
| ''Наживка: Осетр''<!--Sturgeon-->
| ''Наживка на осетра''
|-
| ''Наживка: Солнечник''<!--Sunfish-->
| ''Наживка на солнечника''
|-
| ''Наживка: Чудо-огурец''<!--Super Cucumber-->
| ''Наживка на чудо-огурец''
|-
| ''Наживка: Тигровая форель''<!--Tiger Trout-->
| ''Наживка на тигровую форель''
|-
| ''Наживка: Тиляпия''<!--Tilapia-->
| ''Наживка на тиляпию''
|-
| ''Наживка: Тунец''<!--Tuna-->
| ''Наживка на тунца''
|-
| ''Наживка: Лосось пустоты''<!--Void Salmon-->
| ''Наживка на лосося пустоты''
|-
| ''Наживка: Желтый судак''<!--Walleye-->
| ''Наживка на желтого судака''
|-
| ''Наживка: Лесоплюх''<!--Woodskip-->
| ''Наживка на лесоплюха''
|-
| [[Wine]] (flavored)
| ''Вино из морошки''<!--Salmonberry-->
| ''Малиновое вино''
|}
 
===Furniture===
; Hungarian
: {| class="wikitable"
|-
! item
! old name
! new name
|-
| [[Artist Bookcase]]
| ''Művészi könyvespolc''
| ''Művészi könyvszekrény''
|-
| [[Birch Double Bed]]
| ''Birs dupla ágy''
| ''Nyírfa dupla ágy''
|-
| [[Birch Lamp End Table]]
| ''Nyírfa lámpás éjjeliszekrény''
| ''Nyírfa éjjeliszekrény lámpával''
|-
| [[China Cabinet]]
| ''Kínai vitrin''
| ''Porcelános vitrin''
|-
| [[Coffee Table]]
| ''Kávésasztal''
| ''Kávézó asztal''
|-
| [[Dark Bookcase]]
| ''Sötét könyvespolc''
| ''Sötét könyvszekrény''
|-
| [[Gray Joja Bookcase]]
| ''Szürke Joja könyvespolc''
| ''Szürke Joja könyvszekrény''
|-
| [[Gray Joja Coffee Table]]
| ''Szürke Joja kávésasztal''
| ''Szürke Joja kávézó asztal''
|-
| [[Joja Bookcase]]
| ''Joja könyvespolc''
| ''Joja könyvszekrény''
|-
| [[Joja Coffee Table]]
| ''Joja kávésasztal''
| ''Joja kávézó asztal''
|-
| [[Junimo Bookcase]]
| ''Junimo könyvespolc''
| ''Junimo könyvszekrény''
|-
| [[Large Wizard Bookcase]]
| ''Nagy varázsló könyvespolc''
| ''Nagy varázsló könyvszekrény''
|-
| [[Luxury Bookcase]]
| ''Luxus könyvespolc''
| ''Luxus könyvszekrény''
|-
| [[Mahogany Lamp End Table]]
| ''Mahagóni lámpás éjjeliszekrény''
| ''Mahagóni éjjeliszekrény lámpával''
|-
| [[Modern Bookcase]]
| ''Modern könyvespolc''
| ''Modern könyvszekrény''
|-
| [[Oak Lamp End Table]]
| ''Tölgyfa lámpás éjjeliszekrény''
| ''Tölgyfa éjjeliszekrény lámpával''
|-
| [[Retro Bookcase]]
| ''Retro könyvespolc''
| ''Retro könyvszekrény''
|-
| [[Short Bookcase]]
| ''Kicsi könyvespolc''
| ''Kicsi könyvszekrény''
|-
| [[Short Wizard Bookcase]]
| ''Alacsony varázsló könyvespolc''
| ''Alacsony varázsló könyvszekrény''
|-
| [[Small Wizard Bookcase]]
| ''Kicsi varázsló könyvespolc''
| ''Kicsi varázsló könyvszekrény''
|-
| [[Spirits Table]]
| ''Italosasztal''
| ''Italos asztal''
|-
| [[Walnut Lamp End Table]]
| ''Diófa lámpás éjjeliszekrény''
| ''Diófa éjjeliszekrény lámpával''
|-
| [[Wizard Bookcase]]
| ''Varázsló könyvespolc''
| ''Varázsló könyvszekrény''
|}
 
; Russian
: {| class="wikitable"
|-
! item
! old name
! new name
|-
| [[Pierre's Sign]]
| ''Знак Пьера''
| ''Вывеска Пьера''
|}
 
===Hats===
; French
: {| class="wikitable"
|-
! item
! old name
! new name
|-
| [[Good Ol' Cap]]
| ''Veille casquette''
| ''Vieille casquette''
|}
 
; Russian
: {| class="wikitable"
|-
! item
! old name
! new name
|-
| [[Blobfish Mask]]
| ''Маска рыбы-пузыря''
| ''Маска рыбы-капли''
|-
| [[Bluebird Mask]]
| ''Маска сиалии''
| ''Маска синей птицы''
|-
| [[Cowgal Hat]]
| ''Шляпа девушки-ковбоя''
| ''Женская ковбойская шляпа''
|-
| [[Deluxe Pirate Hat]]
| ''Элитная пиратская шляпа''
| ''Роскошная пиратская шляпа''
|-
| [[Dinosaur Hat]]
| ''Шляпа-динозавр''
| ''Шапка динозавра''
|-
| [[Official Cap]]
| ''Кепка от униформы''
| ''Фуражка''
|-
| [[Panda Hat]]
| ''Шляпка Панды''
| ''Шапка панды''
|-
| Party Hat
| ''Шляпа тусовщика''
| ''Праздничный колпак''
|-
| [[Santa Hat]]
| ''Шляпа Санты''
| ''Шапка Санты''
|-
| [[Star Helmet]]
| ''Звездный шлем''
| ''Шапка со звездами''
|-
| [[Sunglasses]]
| ''Солнечные очки''
| ''Солнцезащитные очки''
|-
| [[Tiger Hat]]
| ''Тигриная шляпа''
| ''Тигриная шапка''
|}
 
===Pants===
; Russian
: {| class="wikitable"
|-
! item
! old name
! new name
|-
| Dinosaur Pants
| ''Динозавровы штаны''
| ''Динозавровые штаны''
|}
 
===Shirts===
; Hungarian
: {| class="wikitable"
|-
! item
! old name
! new name
|-
| Goodnight Shirt
| ''Jóéjt póló''
| ''Jó éjt póló''
|}
 
===Tools===
; Hungarian
: {| class="wikitable"
|-
! item
! old name
! new name
|-
| [[Advanced Iridium Rod]]
| ''Fejlett irídium horgászbot''
| ''Profi irídium horgászbot''
|-
| [[Milk Pail]]
| ''Tejesvödör''
| ''Tejes vödör''
|}
 
===Weapons===
; Hungarian
: {| class="wikitable"
|-
! item
! old name
! new name
|-
| [[Iridium Needle]]
| ''Irídium tű''
| ''Irídiumtű''
|-
| [[Iridium Scythe]]
| ''Irídium kasza''
| ''Irídiumkasza''
|}
 
; Russian
: {| class="wikitable"
|-
! item
! old name
! new name
|-
| [[Abby's Planchette]]
| ''Дощечка Эбби''
| ''Спиритическая планшетка Эбби''
|-
| [[Dark Sword]]
| ''Темный Меч''
| ''Темный клинок''
|-
| [[Dragontooth Club]]
| ''Драконозубья дубинка''
| ''Дубина из драконьего зуба''
|-
| [[Dragontooth Cutlass]]
| ''Драконозубья сабля''
| ''Сабля из драконьего зуба''
|-
| [[Dragontooth Shiv]]
| ''Драконозубья заточка''
| ''Заточка из драконьего зуба''
|-
| [[Dwarf Dagger]]
| ''Кинжал Дварфов''
| ''Дварфийский кинжал''
|-
| [[Dwarf Hammer]]
| ''Молот Дварфов''
| ''Дварфийский молот''
|-
| [[Dwarf Sword]]
| ''Меч Дварфов''
| ''Дварфийский меч''
|-
| [[Insect Head]]
| ''Жучья Голова''
| ''Жучиная голова''
|-
| [[Leah's Whittler]]
| ''Точилка Леи''
| ''Резец Леи''
|-
| [[Seb's Lost Mace]]
| ''Потерянная палица Себа''
| ''Потерянная булава Себа''
|-
| [[Wind Spire]]
| ''Башня Ветров''
| ''Пика ветров''
|}
 
===Monsters===
; Hungarian
: {| class="wikitable"
|-
! monster
! old name
! new name
|-
| [[Truffle Crab]]
| ''Kőrák''
| ''Szarvasgombarák''
|}
 
==XNB impact==
<!--
 
Updated up to 1.6.16 pre-alpha 2025-06-14.
 
-->
===Overview===
This section provides a summary of the XNB files which changed in Stardew Valley 1.6.16. This doesn't include new files (since they won't impact existing mods), text changes in non-English files, or the switch from <samp>\</samp> to <samp>/</samp> in asset names (since that's backwards compatible).
 
[[Modding:Using XNB mods|XNB mods]] are disproportionately affected, since...
# they replace the entire file;
# they're loaded through the MonoGame content pipeline which is less tolerant of format changes;
# they don't benefit from the compatibility rewrites [[Modding:Content Patcher|Content Patcher]] provides for its content packs.
 
Content Patcher packs are typically unaffected (and Content Patcher will try to rewrite content packs automatically). However if a content pack replaces an entire asset instead of editing, it's more likely to be affected like an XNB mod.
 
===Changed assets===
Compatibility is broadly grouped into four categories:
* "'''✘ broken'''": mods will remove new content or significant changes, or the mod's intended changes will no longer work. Effects may range from display bugs to crashes, depending how the game uses that specific content.
* "✘ will remove changes": mods will remove minor changes in 1.6.16 (e.g. typo fixes).
* "✓ mostly unaffected": mods will only be affected if they replace the entire asset, or edit specific entries or fields.
* Blank: no expected impact for the vast majority of mods.
 
{| class="wikitable"
|-
!rowspan="2"| content asset
!rowspan="2"| changes in 1.6.16
!colspan="2"| compatibility for pre-1.6.16 mods
|-
! XNB mods
! Content Patcher packs
|-
| <samp>Characters/Dialogue/*</samp>
| &#32;
* Removed now-unneeded <samp>%fork</samp> tokens.
* Fixed bugs & typos.
| ✘ will remove fixes.
|
|-
| <samp>Data/Boots</samp>
| [[#Data/Boots|Overhauled format]].
| '''✘ broken'''
| '''✘ broken'''<br /><small>(until Content Patcher adds runtime migrations)</small>
|-
| <samp>Data/Buffs</samp>
| [[#Data/Buffs|Added new data fields]].
| '''✘ broken'''
|
|-
| <samp>Data/CookingRecipes</samp>
| [[#Data/CookingRecipes|Changed several recipe keys]].
| '''✘ broken'''
| ✓ mostly unaffected<br /><small>(until Content Patcher adds runtime migrations)</small>
|-
| <samp>Data/Events/*</samp><br /><samp>Data/Events/Festivals/*</samp>
| &#32;
* Migrated to [[#Multilingual events|multilingual events]] and [[#Forking deprecated|event labels]].
* [[#Changed event keys|Changed some event keys]].
* Replaced most <samp>awardFestivalPrize</samp> commands with <samp>addItem</samp>.
* Significant changes to support above migrations (e.g. replacing dialogue commands with event commands).
| '''✘ broken'''
| ✓ mostly unaffected
|-
| <samp>Data/ExtraDialogues</samp>
| &#32;
* [[#Event changes|Removed hardcoded events]].
* Moved <samp>SummitEvent_*</samp> translations into <samp>Strings/Events</samp> (with a different name & format).
| ✓ mostly unaffected
| ✓ mostly unaffected
|-
| <samp>Data/Furniture</samp>
| &#32;
* [[#Data/Furniture|Overhauled format]].
* Removed <samp>Rotations</samp> field for [[Decorative Joja Door|decorative Joja door]].
| '''✘ broken'''
| '''✘ broken'''<br /><small>(until Content Patcher adds runtime migrations)</small>
|-
| <samp>Data/Hats</samp>
| &#32;
* [[#Data/Hats|Overhauled format]].
* Standardized asset name capitalization (<samp>Data/hats</samp> → <samp>Data/Hats</samp>).
| '''✘ broken'''
| '''✘ broken'''<br /><small>(until Content Patcher adds runtime migrations)</small>
|-
| <samp>Data/LocationContexts</samp>
| Changed weather conditions to fix re-randomization issue.
| ✘ will remove fixes.
| ✓ mostly unaffected.
|-
| <samp>Data/Locations</samp>
| Changed [[Legend]] condition to use new <samp>IS_RAINING</samp> [[Modding:Game state queries|query]] to support mods weathers.
| ✘ will remove fixes.
| ✓ mostly unaffected.
|-
| <samp>Data/LostItemsShop</samp>
| [[#Data/LostItemsShop|Added new field]].
| '''✘ broken'''
|
|-
| <samp>Data/Monsters</samp>
| [[#Data/Monsters|Overhauled format]].
| '''✘ broken'''
| '''✘ broken'''<br /><small>(until Content Patcher adds runtime migrations)</small>
|-
| <samp>Data/Objects</samp>
| Added [[#Data/Objects|new fields]] and [[#New context tags|new context tags]].
| '''✘ broken'''
|
|-
| <samp>Data/SpecialOrders</samp>
| [[#Data/SpecialOrders|Added new fields]].
| '''✘ broken'''
|
|-
| <samp>Data/Tools</samp>
| &#32;
* [[#Data/Tools|Added new fields]].
* Removed <samp>Lantern</samp> tool.
| '''✘ broken'''
|
|-
| <samp>Data/Weapons</samp>
| [[#Data/Weapons|Added new fields]].
| '''✘ broken'''
|
|-
| <samp>Data/Weddings</samp>
| Fixed Lewis skipping his matrimonial dialogue at the farmer's wedding.
| ✘ will remove fix
| ✓ mostly unaffected
|-
| <samp>Maps/Bus(people)</samp><br /><samp>Maps/busPeople</samp><br /><samp>Maps/Island_Secret</samp>
| Removed (these were unused).
|
|
|-
| <samp>Strings/Events</samp>
| Added the translations for [[#Multilingual events|multilingual events]].
| '''✘ broken'''
|
|-
| <samp>Strings/1_6_Strings</samp>
| &#32;
* [[#Event changes|Removed hardcoded events]].
* Moved some translations into <samp>Strings/Events</samp> and <samp>Strings/Furniture</samp>.
| ✓ mostly unaffected
| ✓ mostly unaffected
|-
| <samp>Strings/Furniture</samp>
| Added translations for catalogue descriptions (moved from <samp>Strings/1_6_Strings</samp>).
| '''✘ broken'''
|
|-
|-
| <samp>Strings/Locations</samp>
| <samp>Strings/Locations</samp>
| [[#Event changes|Removed hardcoded events]].
| <samp>SeedShop_BuyBackpack_ResponseNo</samp>
| ✓ mostly unaffected
| Key renamed to <samp>GenericPurchase_Decline</samp>.
| ✓ mostly unaffected
|-
| <samp>Strings/Objects</samp>
| Moved some translations into <samp>Strings/Furniture</samp>.
| ✓ mostly unaffected
| ✓ mostly unaffected
|-
| <samp>Strings/StringsFromCSFiles</samp><br /><samp>Strings/Tools</samp>
| Removed some unused translations.
|
|
|-
| <samp>Strings/UI</samp>
| Merged male/female variants of <samp>PondQuery_StatusRequestPending_*</samp> entries.
| '''✘ broken'''
| ✓ mostly unaffected
|}
|}
<!--
===Removed unused assets===
Stardew Valley 1.6.16 deletes assets which weren't used by the game. Mods usually aren't affected by this.
TODO
-->


[[Category:Modding]]
[[Category:Modding]]


[[zh:模组:迁移至游戏本体1.6.16]]
[[zh:模组:迁移至游戏本体1.7]]

Latest revision as of 12:17, 28 September 2026

←Index

This page is for mod authors. Players: see the mod compatibility list instead.

⚠ Stardew Valley 1.7 was announced, but has no planned release date.
There's no estimate for when the update will be released, so don't plan mod updates around the 1.7 release. Things will change before it's released!

This page helps mod authors prepare their mods for the upcoming Stardew Valley 1.7, and documents some of the changes and new functionality.

FAQs

SMAPI mod compatibility over time.

What's changing?

Stardew Valley 1.7 makes significant changes to many data assets to enable new game features and mod extensibility. See the sections below for more details.

Is this the modapocalypse?

Probably not. SMAPI and Content Patcher will automatically rewrite older mods for many of the changes, so they should still work as-is. Some mods may need an update.

How to update your mod

Here's a suggested 'quick start' guide to update a mod for Stardew Valley 1.7.

For C# mods:
  1. Update for Stardew Valley 1.6.16 if you haven't already.
  2. Rebuild the solution.
  3. Fix any build errors and review any build warnings. You can search this page and previous migration guides for relevant info as needed.
  4. Increment your mod version in manifest.json.
    (Some mods may be added to SMAPI's compatibility blacklist due to runtime errors. Incrementing the mod version will fix that if so.)
  5. Test to make sure the mod works.
  6. Skim through this page, and check any section that might be relevant to the mod.
For Content Patcher packs:
  1. Update for Stardew Valley 1.6.16 if you haven't already.
  2. Skim through this page, and check any section that might be relevant to the mod.
For content packs which use another framework:
See the documentation for the framework mod. Often you won't need to update the content pack if the framework mod itself was updated.

Data asset changes

Data/Boots

This has been overhauled into a data model asset, with translations moved into a new Strings/Boots asset. This also includes new fields like ContextTags and CustomFields which weren't available in the old format.

The data asset now consists of a string → model lookup, where...

field effect
basic info
Name The internal item name (not shown in-game).
DisplayName
Description
A tokenizable string for the item's in-game display name and description.
ContextTags (Optional) The custom context tags to add for this item (in addition to the tags added automatically based on the other item data), specified as an array.
equipment effects
AddDefense
AddImmunity
(Optional) A bonus applied to the player's defense or immunity stats when the boots are equipped. Default 0.
appearance
Texture The asset name for the texture containing the boots sprite. Defaults to Maps/springobjects if omitted, but should always be specified for custom boots.
SpriteIndex (Optional) The sprite's index within the Texture, where 0 is the top-left sprite. Default 0.
ColorTexture (Optional) The asset name for the texture containing the boots color sprite. Defaults to Characters/Farmer/shoeColors if omitted.
ColorSpriteIndex (Optional) The color sprite's index within the ColorTexture, where 0 is the top-left sprite. Default 0.
advanced
CustomFields (Optional) The custom fields for this entry.

For example, here's how to add new boots in 1.7:

{
    "Format": "2.8.0",
    "Changes": [
        // add data
        {
            "Action": "EditData",
            "Target": "Data/Boots",
            "Entries": {
                "{{ModId}}_FancyBoots": {
                    "Name": "{{ModId}}_FancyBoots",
                    "DisplayName": "{{i18n: fancy-boots.name}}",
                    "Description": "{{i18n: fancy-boots.description}}",
                    "Texture": "Mods/{{ModId}}/Boots",
                    "SpriteIndex": 0,
                    "ColorSpriteIndex": 1
                }
            }
        },

        // add texture
        {
            "Action": "Load",
            "Target": "Mods/{{ModId}}/Boots",
            "FromFile": "assets/boots.png"
        }
    ]
}

Data/Buffs

Added one new field to buff attributes, contained in the Effects field:

field effect
CustomFields (Optional) The custom fields for this entry.

Data/Characters

The following fields have been added:

field effect
FlowerDanceBehavior (Optional) A list of behaviors to consider for use during the Flower Festival. If no matching ones are found, the default behavior for that NPC's gender is used.

Each entry in this list has the following fields:

field effect
Id An ID for this entry within the dance behavior list. This only needs to be unique within the current list.
Condition A game state query which indicates whether this entry is a valid choice. Default true.
Sprite The sprite to use for the dance, as would be passed in to the changeSprite event command. Default null.
FirstDanceFrame The first frame of the relevant spritesheet to use for the dance animation.

The animation frames after this index must still follow the standard structure.

Precedence The order in which this behavior should be checked, where 0 is the default value used by most behaviors.

Data/CraftingRecipes and Data/CookingRecipes

Crafting recipes and cooking recipes are now a data model. The data model for both are identical. Crafting recipes still live in Data/CraftingRecipes, and cooking recipes still live in Data/CookingRecipes.

Both assets are dictionary assets. The key is the recipe ID, the same as in 1.6, and the value is a data model with the following fields:

field effect
DisplayName A tokenizable string for the display name of this recipe.
Description A tokenizable string for the description of this recipe.
Ingredients A list of ingredients for this recipe.
field effect
Id TThe unique string ID for this entry (not the item itself) within the current list.

This is semi-optional — if omitted, it'll be auto-generated from ItemId. However multiple entries with the same ID may cause unintended behavior, so it's often a good idea to set a globally unique ID instead.

ItemId The item for this ingredient. This can be either a qualified item ID, or a context tag.

If a context tag is specified, it needs to have a corresponding entry in Data/ContextTags.

Quantity The amount of this ingredient to require. Default 1.
Condition The game state query for this ingredient. If not specified, defaults to TRUE.
CustomFields (Optional) The custom fields for this entry.
Result The possible results for this recipe. This is a list of conditional item spawn fields.

If there are multiple resulting possibilities at once, the one chosen for display in menus uses the following precedence:

  1. First, it checks the recipe's DisplayItemId.
  2. If there was no DisplayItemId, then it will search all results for the first one that is not conditional (eg. Condition is either null or TRUE).
  3. If no unconditional results were found, then it chooses the first result, regardless of if the condition passes.
DisplayItemId A qualified item ID to override the displayed item in menus.
Unlock The unlock conditions for this recipe.
field effect
Trigger
name effect
DayStart Checks the Condition at the beginning of each day.
Mail Checks the Condition at the beginning of each day, and queues MailLetterName for the mailbox if the condition passed.
LevelUp Appears when reaching a level RequiredSkillLevel in the RequiredSkill skill. Condition is ignored.
Default Added as a default recipe. Condition is ignored.
Condition The game state query for this unlock. If not specified, defaults to TRUE.
RequiredSkill The skill for the required level for this unlock, if Trigger is equal to LevelUp.
RequiredSkillLevel The required level for this unlock, if Trigger is equal to LevelUp.
MailLetterName The name of letter sent for unlock, if Trigger is equal to Mail.
CustomFields (Optional) The custom fields for this entry.
ExcludeFromPerfection Whether or not to exclude this recipe from perfection checks. Default false.
CustomFields (Optional) The custom fields for this entry.

Data/GiftTastes

Gift tastes, previously in Data/NPCGiftTastes with a localized version for every language, are now in Data/GiftTastes (taste data only) and Strings/GiftTasteReactions (reaction strings, one per language).

Responses to gifts are pulled from Strings/GiftTasteReactions, with the entry chosen from the following format: {NPC}_{Taste}, with {NPC} being the NPC ID, and {Taste} being the corresponding taste (ex. Penny_Love for Penny's loved gift response).

For the gift taste data itself, it now works based on a precedence and game state query system. Additionally, a gift taste can apply to multiple NPCs at once.

Data/GiftTastes is a list of gift taste entries, with the following format:

field effect
Id The ID of this entry.
Condition (Optional) The game state query for if this gift taste should apply, if any.
Precedence (Optional, but recommended) The precedence for this entry, with higher values being checked first.

For the precedence decided for various base game's gift tastes, see the notes after this table.

ItemId The item that matches this gift taste. This can be a qualified item ID, a category, or a context tag query.
Taste The gift taste that applies for this entry. Possible values are Love, Like, Neutral, Dislike, and Hate.
AppliesTo (Optional) Who this gift taste applies to. This is a comma-separated list of NPC names.

If not specified, applies to all NPCs.

advanced
CustomFields (Optional) The custom fields for this entry.

Precedences for old gift taste data

When converting the base game's legacy gift taste data, the precedence values were determined in a way to match previous behavior.

First, a base precedence was chosen based on who it applied to and what type of match it was:

base precedence who what
0 Specific character Specific item
-1000 Specific character Items matching a context tag
-2000 Universal Specific item
-3000 Specific character Items of a specific category
-4000 Universal Items matching a context tag
-5000 Universal Items of a specific category

After the base precedence is selected, an additional value is added based on the resulting gift taste.

precedence modifier legacy gift taste
400 Love
300 Hate
200 Like
100 Dislike
0 Neutral

Additionally, the previously hard-coded behavior of everyone disliking artifacts (except Penny and the Dwarf, who like them) are now in the data, with a precedence of -1250 (universal dislike) and -1200 (Penny and Dwarf like).

Certain fallback behavior for cheap or negative ediblity otherwise-neutral-reaction items are still hardcoded, but still only apply if:

  • the chosen gift taste was neutral
  • the chosen gift taste applies to everyone (ie. was universal)
  • the chosen gift taste was for that specific item, and not an entire category or context tag

Data/Furniture

This has been overhauled into a data model asset. The overhaul also adds support for previously-hardcoded features like custom item descriptions (via Description), custom TVs (via the new Television furniture type and TelevisionScreen* fields), and custom fields.

The data asset now consists of a string → model lookup, where...

field effect
basic info
Name The internal item name (not shown in-game).
DisplayName A tokenizable string for the item's in-game display name.
Description (Optional) A tokenizable string for the item's in-game description. Defaults to a generic description based on the other fields like CanPlaceIndoors and CanPlaceOutdoors.
Type (Optional) The furniture type, which affects various furniture functionality and default values (e.g. default bounding box size). Defaults to Other.

See table of valid types.

Price (Optional) The price for this furniture when purchased from a shop. Default 0.
ContextTags (Optional) The custom context tags to add for this item (in addition to the tags added automatically based on the other item data), specified as an array.
behavior
CanPlaceIndoors
CanPlaceOutdoors
(Optional) Whether the player can place this furniture indoors and/or outdoors. Defaults to generic behavior based on the Type field (e.g. TVs can't be placed outdoors by default).
ExcludeFromRandomSale (Optional) Whether to prevent this furniture from being shown in randomly generated shop stock or furniture catalogues. Default false.
appearance
Texture The asset name for the texture containing the furniture sprite. Defaults to TileSheets/furniture if omitted, but should always be specified for custom furniture.
SpriteIndex (Optional) The sprite's index within the Texture, where 0 is the top-left sprite. Default 0.
Rotations (Optional) The number of rotations possible (1, 2, or 4). Default 1.
SpriteSize (Optional) The sprite's size in the Texture, measured in tiles. Defaults to a generic size depending on the Type field.
BoundingBoxSize (Optional) The collision box size when the furniture is placed in-game, measured in tiles. Defaults to a generic size depending on the Type field.

The bounding box is anchored to the bottom-left corner of the SpriteSize. Width will push the right side of the box to the right, height will push the top of the box upwards.

type-specific options
BedType (Optional) When the Type field is set to Bed, the bed type which affects who can sleep in it. Default Single.

Valid values:

bed type effect
Single A single-sized bed with room for one player or NPC.
Double A double-sized bed with room for two players or NPCs.
Child A single bed for a child NPC.
BedUpgradeItemId (Optional) When the Type field is set to Bed, the item ID of the double bed to replace with for house upgrades. Default null.

If omitted, when choosing a double bed for an upgraded Farmhouse or Cabin, a legacy integer ItemId will result in a value of ItemId + 4, otherwise the default value of 2052 will be used.

TelevisionScreenOffset (Optional) When the Type field is set to Television, the X and Y pixel offset relative to the TV's bounding box to apply when drawing the screen image onto the TV. Default none.
TelevisionScreenScale (Optional) When the Type field is set to Television, the zoom multiplier to apply to the screen image so it fits onto the TV's screen.
advanced
CustomFields (Optional) The custom fields for this entry.

Data/Hats

This has been overhauled into a data model asset, with translations moved into a new Strings/Hats asset. This also includes new fields like ContextTags and CustomFields which weren't available in the old format.

The data asset now consists of a string → model lookup, where...

field effect
basic info
Name The internal item name (not shown in-game).
DisplayName
Description
A tokenizable string for the item's in-game display name and description.
HairStyle (Optional) What to do about the player's hair when they wear this hat. Default DrawObscuredHair.

The possible values are:

  • DrawFullHair: the hair is drawn like usual (e.g. for hats that don't hide the hair like Abigail's bow).
  • DrawObscuredHair: the hair is partly obscured under the hat (e.g. for most hats like the cowboy hat).
  • HideHair: the hair is fully hidden (e.g. for hats which fully cover the head like the mummy mask).
SkipHairOffset (Optional) Whether to skip offsetting the hat to sit 'on top' of the player's current hairstyle (e.g. for masks). Default false.
Texture The asset name for the texture containing the hat sprite. Defaults to Characters/Farmer/hats if omitted, but should always be specified for custom hats.
SpriteIndex (Optional) The sprite's index within the Texture, where 0 is the top-left sprite. Default 0.
ContextTags (Optional) The custom context tags to add for this item (in addition to the tags added automatically based on the other item data), specified as an array.
CustomFields (Optional) The custom fields for this entry.

For example, here's how to add a new hat in 1.7:

{
    "Format": "2.8.0",
    "Changes": [
        // add data
        {
            "Action": "EditData",
            "Target": "Data/Hats",
            "Entries": {
                "{{ModId}}_FancyHat": {
                    "Name": "{{ModId}}_FancyHat",
                    "DisplayName": "{{i18n: fancy-hat.name}}",
                    "Description": "{{i18n: fancy-hat.description}}",
                    "HairStyle": "DrawObscuredHair",
                    "Texture": "Mods/{{ModId}}/Hats",
                    "SpriteIndex": 0
                }
            }
        },

        // add texture
        {
            "Action": "Load",
            "Target": "Mods/{{ModId}}/Hats",
            "FromFile": "assets/hats.png"
        }
    ]
}

Data/Monsters

Monster data has been completely rethought in Stardew Valley 1.7. In particular...

  • For monster data in general:
    • Data/Monsters has been been overhauled into a data model asset, with translations moved into a new Strings/Monsters asset. This includes significant new features which weren't supported with the old format.
    • A new 'monster variant' concept lets multiple specific monsters share common data (e.g. Green Slime and Tiger Slime are variants of the new base Slime monster). This is particularly used for common drops.
    • A new 'monster tag' system lets monster define custom tags like slime_is_prismatic, which can be used to filter monster drops.
  • For monster drops:
    • A rethought monster drop system supports the full range of vanilla features like conditions, item queries, qualified item IDs for non-object drops, and monster-specific concepts like repeating drop chance and mutually-exclusive drops.
    • All drops are now qualified item IDs. The former 'resource IDs' (formatted as negative numbers like -4) are no longer supported; items are converted into their equivalent resource debris automatically where needed.
    • Nearly all monster drops are now defined in Data/Monsters (with just a few hardcoded drops common to all monsters left).

The data asset now consists of a string → model lookup, where...

  • The key is the unique string ID.
  • The value is a model with the fields listed below.
field effect
basic info
DisplayName A tokenizable string for the monster's display name.
IsGlider (Optional) Whether the monster is flying (e.g. so they glide over obstacles). Default false.
IsMineMonster (Optional) Whether this monster spawns in the mines, and should be buffed after the player reaches the bottom. This sometimes applies to monsters that can appear elsewhere too (e.g. wilderness golems on the farm receive mine buffs too). Default false.
ExperiencePoints (Optional) The combat experience points received for defeating the monster. Default 1.
stats
Health (Optional) The initial hit points. Default 20.
Attack (Optional) The attack power (i.e. how much damage its hits inflict on players). Default 5.
Defense (Optional) The defense which reduces damage received by this monster. Default 0.
DodgeChance (Optional) The percentage chance that the monster dodges an attack, as a value between 0 (never) and 1 (always). Default 0.
Speed (Optional) The default movement speed. Default 1.
Jitteriness (Optional) How often the monster will move in random non-player directions to try to get around objects, as a value between 0 (never) and 1 (always). Default 0.1.
DetectionDistance (Optional) The distance at which the monster detects a player and begins moving towards them, or -1 for unlimited. Default 4.
drops
Drops (Optional) The items which can drop when the monster is defeated. Default none.

All matching entries are dropped. If the player has a burglar's ring equipped, each entry will make two attempts to drop (but fields like RepeatingChance and SkipIfDropped are independent between the two attempts).

This consists of a list of models with these fields:

field effect
common fields See item spawn fields for the generic item fields supported for monster drops.

Notes:

  • If a drop has an item query which returns multiple item stacks, one of them will be selected at random.
  • The Condition field can optionally contain the %RANDOM_KEY token, which is set to a unique identifier for this monster during the current tick.
ForTags (Optional) The monster tags for which this drop applies. This can be a context tag-like query string like !variant_frost_bat, !variant_lava_bat (not frost bat or lava bat). Default none, meaning it applies to all monsters with this data.
Chance (Optional) A probability that this item will be found, as a value between 0 (never) and 1 (always). Default 1.
RepeatingChance (Optional) A compounding probability of an extra drop, as a value between 0 (never) and .95 (nearly always). Default 0.

This applies after an item has been dropped based on the other fields. This chance is repeatedly checked to produce an extra drop until it fails. Each repeat drop will ignore the Chance and Condition fields, but reapply all other item spawn fields (e.g. re-selecting RandomItemId if applicable).

RepeatingChanceKey (Optional) When checking the RepeatingChance field, use this to seed a predictable RNG. This can be used to synchronize separate drops. Default none.

This can optionally contain the %RANDOM_KEY token, which is set to a unique identifier for this monster during the current tick.

ExplodeStack (Optional) Whether to split multi-item stacks into single-item stacks. Default false.

For example, let's say a monster would drop a stack of 15 wood. With this option enabled, it would instead drop 15 stacks of one wood each.

SkipIfDropped (Optional) Skip the current entry if one of these drop IDs have already been dropped. Default none.

This is specified as an array. For example:

"SkipIfDropped": [ "ExampleDropId", "AnotherDropId" ]
tags
ContextTags (Optional) The context tags to add for this monster, in addition to those added automatically based on the other fields. Default none.
variants
DefaultVariant (Optional) When the game creates a monster of this type without specifying a variant, use the given variant instead of creating it from only the base data. Default false.
Variants (Optional) The possible variations of this monster. Default none.

Each variant is simply a set of fields which override the base data when set. For example, this creates a variant which only differs from the base monster by name and health points:

"Variants": [
    {
        "DisplayName": "{{i18n: variant-name}}",
        "Health": 50
    }

This consists of a list of models with these fields:

field effect
monster fields All monster fields (except DefaultVariant and Variants) can be set on the variant. All fields are optional, and default to the value set in the monster's base data.
InheritDrops (Optional) Whether to inherit drops defined in the monster's base Drops field. Default true.

Specifically:

  • If true, the variant will combine the base Drops and variant Drops into one list.
  • If false, only drops in the variant Drops field are applied.
advanced
CustomFields (Optional) The custom fields for this entry.

For example, this Content Patcher code adds a new 'Pufferchick' monster which drops pufferfish when defeated. The monster's spritesheet is automatically loaded from Monsters/<ID>.

Note: this only adds the monster data. Currently this does nothing unless you have another mod which spawns instances of the monster in-game.

{
    "Format": "2.8.0",
    "Changes": [
        // add data
        {
            "Action": "EditData",
            "Target": "Data/Monsters",
            "Entries": {
                "{{ModId}}_Pufferchick": {
                    "DisplayName": "{{i18n: pufferchick.name}}",
                    "ExperiencePoints": 3,

                    "Health": 30,
                    "Attack": 2,
                    "Defense": 5,
                    "DodgeChance": 0.3,
                    "Speed": 2,
                    "DetectionDistance": 2,

                    "Drops": [
                        {
                            "Id": "Pufferfish",
                            "ItemId": "(O)128",
                            "Chance": 0.5,
                            "RepeatingChance": 0.1
                        }
                    ]
                }
            }
        },

        // add texture
        {
            "Action": "Load",
            "Target": "Monsters/{{ModId}}_Pufferchick",
            "FromFile": "assets/pufferchick.png"
        }
    ]
}

Schedule data

Schedules have been changed into data models. Previously under Characters/schedules, now under Characters/ScheduleData.

field effect
Precedence The precedence of this entry. A higher precedence will be checked first.

Note: the hardcoded schedules for visiting Ginger Island will override everything below precedence 100000.

Season (Optional) The season that this schedule applies to, if any. If not specified, applies to any season.
DayOfMonth (Optional) The day of month that this schedule applies to, if any. If not specified, applies to any day of the month.
WeekDay (Optional) The week day that this schedule applies to, if any. If not specified, applies to any day of the week.

This accepts the short name of the day of week, ex. Mon, Tue, Wed, ...

RequiredHearts (Optional) The minimum amount of friendship (in hearts) for this schedule to apply, if any. If not specified, applies regardless of friendship level.
Condition (Optional) A game state query for if this entry should apply, in addition to the other fields. If not specified, treated as TRUE.
StartLocationOverride (Optional) Override the location to start the day in when this schedule is chosen. StartTileOverride must also be specified for this to apply.

Requires StartTileOverride to be specified for this to work.

StartTileOverride (Optional) Override the tile to start the day on when this schedule is chosen. StartLocationOverride must also be specified for this to apply.

Requires StartLocationOverride to be specified for this to work.

StartFacingDirectionOverride (Optional) Override the facing direction to start the day with when this schedule is chosen. StartLocationOverride must also be specified for this to apply.

Requires StartLocationOverride to be specified for this to work.

StartEndOfRouteAnimation (Optional) Override the end of route animation to start the day with when this schedule is chosen. StartLocationOverride must also be specified for this to apply.

Requires StartLocationOverride to be specified for this to work.

StartEndOfRouteMessage (Optional) Override the end of route message to start the day with when this schedule is chosen. StartLocationOverride must also be specified for this to apply.

Requires StartLocationOverride to be specified for this to work.

FallbackSchedules (Optional) A list of additional schedules options that, if the corresponding GSQ passes, will revert to that schedule instead. Intended for "fail conditions" (ex. one of the locations in this schedule are not currently accessible).
field effect
Condition The game state query to check for this fallback option.
Schedule The schedule to use if the condition passed for this fallback option.

If this is "season", it will act check "spring", "summer", "fall", or "winter" based on the current game's season. IF this is "no_schedule", then the NPC will have no schedule for that day.

CustomFields (Optional) Custom fields for mods to use.
Commands A list of commands for the schedule.
field effect
Type (Optional) The type of this schedule command. Defaults to Depart
type meaning
Depart The NPC will depart at the specified time.
Arrive The NPC will try to arrive at the specified time.
Bed The NPC will try to return to their bed.
Time The time for this schedule command. This must be a time after the previous command's time.

Note: a time of 0 (for "0 schedules") is no longer supported. For the equivalent behavior, use StartLocationOverride and friends.

DestinationLocation (Only applies for Type = Depart or Arrive) The location that this command takes the NPC to.
Destination (Only applies for Type = Depart or Arrive) The tile in the location that this command takes the NPC to.
DestinationFacingDirection (Optional, only applies for Type = Depart or Arrive)) The facing direction that should be used when arriving at this command's target.
EndOfRouteAnimation (Optional) The animation from Data/animationDescriptions to play upon ending this NPC.
EndOfRouteMessage (Optional) The localized string key to say if a player talks to this NPC after ending this command, but before the next one.
CustomFields (Optional) Custom fields for mods to use.
CustomFields (Optional) Custom fields for mods to use.

The vanilla schedules were all converted using this automated script, which is under the MIT license.

Data/Objects

Added new fields:

field effect
Buffs This field already existed, but has a field change:
field effect
CustomAttributes This field already existed, but has one new field:
field effect
CustomFields (Optional) The custom fields for this entry.
UseCondition A game state query for determining if the object is usable on right click. If not specified, equivalent to "TRUE".
UseConditionFailedMessage A tokenizable string for what message to show when UseCondition is not met. If an empty string, no message will be shown. If not specified, equivalent to "[LocalizedText Strings/UI:CantUseHere]".
UseActions A list of actions to run upon using the item. These trigger actions will have an input argument called StackSize, which will be the size of the stack obtained if triggered via ConsumeOnObtain, or 1 otherwise. (For more information on trigger action input arguments, see the relevant section on this page.)
ConsumeOnUse true if the item should be consumed on use, false otherwise. Default true.
ObtainActions A list of actions to run upon obtaining the item. These trigger actions will have an input argument called StackSize, which will be the size of the stack obtained. (For more information on trigger action input arguments, see the relevant section on this page.)
ConsumeOnObtain If the item should be automatically used *and* consumed when obtained. Items with this enabled:
  • Will not actually enter the inventory (since they are consumed immediately).
  • Can be collected even with a full inventory (since they are consumed immediately).
  • Will not have their UseCondition checked before their UseActions are run.
  • Will have their ObtainActions (if any) run before their UseActions are run.
ShowNotificationOnObtain true if the item should show a notification in the bottom left corner of the screen upon receiving the item, false otherwise. Default true.
ForgeRandomSlot The slot to randomize the enchantments for if this is used as an ingredient.
ForgeCost If greater than or equal to 0, the cinder shard cost for using this item in the forge.
ForgeCostItem If set, changes the item required for forging from cinder shards to something else.

Data/Weapons

Added new fields:

field effect
DefaultEnchantments Enchantments to apply by default on this weapon. This is a dictionary, with the key being the enchantment ID, and the value being the level of the enchantment.

Enchantments added through this are still subject to normal enchantment restrictions, and therefore must actually be applicable to this weapon.

For an example of this, check out the Holy Blade.

Changes for all mod authors

Switch blocks

'Switch blocks' are a new ${…}$ syntax which can be used in nearly all game text (not just dialogue). This extends the former 'gender-switch blocks' added in 1.6.0.

These are applied before most other commands or parsing, so you can safely use them in cases where characters like ^ have a different meaning (e.g. mail text).

The supported switch blocks are:

type syntax description
gender ${male^female}
${male^female^non-binary}
Switch between text for male, female, and non-binary players. The non-binary value is only used if a mod overrides the player's gender, since the in-game UI only allows male or female.

You can also use ¦ instead of ^, in which case any ^ characters are left as-is.

For example:

"Mon": "Hey ${lad^lass^kiddo}$!"
randomize ${variant A ||| …}$ Defines an arbitrary number of variants from which to choose each day. After randomization, any leading or trailing whitespace is trimmed. This randomization is deterministic per day (e.g. reloading the save won't change which one is shown).

For example, let's say you did this:

"Rainy_Night": "I ${love ||| like ||| adore ||| somewhat enjoy ||| enjoy}$ rain.$h"

That would create five variants which each have an equal probability of being selected.

Switch blocks can be arbitrary combined and nested. For example:

"Rainy_Night": "${Hello there ||| Hey ${lad^lass^kiddo}$ }$!"

Context tag changes

Added new context tags:

context tag item types effect
is_galaxy_weapon weapons Marks the tool as a galaxy weapon like the galaxy hammer or galaxy sword. This is set for vanilla scythes through Data/Weapons. This affects logic which checks for galaxy weapons (e.g. galaxy soul enchantments).

Additionally, there is now a data asset for context tags for supporting data (such as for using them in crafting recipes). Located in Data/ContextTags, this is a dictionary assets. The key is the context tag, and the value is a data model with the following fields:

field effect
DisplayName A tokenizable string for the display name of this context tag. Required when using a context tag as a crafting recipe ingredient.
RepresentativeItem The qualified item ID for the item representing this context tag. Required when using a context tag as a crafting recipe ingredient.
CustomFields (Optional) The custom fields for this entry.

Dialogue changes

  • Added a new special token in dialogue strings:
    token description
    ||| This is a shortcut for the randomize switch block.

    Delimits an arbitrary number of dialogue variants from which to choose each day. After randomization, any leading or trailing whitespace is trimmed. This randomization is deterministic per day (e.g. reloading the save won't change which one is shown).

    For example, let's say you did this:

    "Rainy_Night": "
        I love rain.$h|||
        I like rain.$h|||
        I adore rain.$h|||
        I hate rain.$s#$b#Just kidding. I love it!$h|||
        I enjoy rain.$h
    "
    

    That would create five variants of the dialogue which each have an equal probability of being selected.

  • Improved some special tokens:
    token changes
    || Whitespace around the token is now ignored, so you can split text into multiple lines:
    "Wed8": "
        Isn't it expensive, coming to the desert so often like you do?#$e#You must really like to see me, huh? Hmmm... $h||
        *sigh*... I do miss the beautiful flowers of Stardew Valley...$s
    "
    
  • Some dialogues were merged or renamed using the new features. The previous dialogue keys are now ignored by the game.
    asset former key changes
    Characters/Dialogue/<NPC name> Resort_<number>
    Resort_Bar_<number>
    Resort_Chair_<number>
    Resort_Dance_<number>
    Resort_Shore_<number>
    Resort_Towel_<number>
    Resort_Umbrella_<number>
    Resort_Wander_<number>
    Merged into their base key (e.g. Resort_<random> into Resort) using the new ||| random-variant token.
    Characters/Dialogue/MarriageDialogue
    Characters/Dialogue/MarriageDialogue<NPC name>
    Characters/Dialogue/MarriageDialogue<NPC name>Roommates
    funLeave_<NPC name>
    funReturn_<NPC name>
    jobLeave_<NPC name>
    jobReturn_<NPC name>

    patio_<NPC name>
    spouseRoom_<NPC name>

    spring_<NPC name>
    summer_<NPC name>
    fall_<NPC name>
    winter_<NPC name>
    Moved into MarriageDialogue<NPC name> and removed the NPC suffix (like spouseRoom_<NPC name> → spouseRoom).
    Indoor_Day_0
    Indoor_Day_1
    Indoor_Day_2
    Indoor_Day_3
    Indoor_Day_4
    Merged into Indoor_Day.
    Indoor_Night_0
    Indoor_Night_1
    Indoor_Night_2
    Indoor_Night_3
    Indoor_Night_4
    Indoor_Night_<NPC name>
    Merged into Indoor_Night.
    NoBed_0
    NoBed_1
    NoBed_2
    NoBed_3
    Merged into NoBed.
    Outdoor_0
    Outdoor_1
    Outdoor_2
    Outdoor_3
    Outdoor_4
    Outdoor_<NPC name>
    Merged into Outdoor.
    Rainy_Day_0
    Rainy_Day_1
    Rainy_Day_2
    Rainy_Day_3
    Rainy_Day_4
    Merged into Rainy_Day.
    Rainy_Night_0
    Rainy_Night_1
    Rainy_Night_2
    Rainy_Night_3
    Rainy_Night_4
    Rainy_Night_5
    Rainy_Night_<NPC name>
    Merged into Rainy_Night.

Display shops

In addition to being able to add or change what is sold on Pierre's counter, you can also create your own.

Display shops are similar to normal shops, except they show their stocked items in-world. They have a fixed size which is filled from the item pool until it is full (or there is nothing left to add).

Display shops are stocked at the beginning of the day, and not restocked until the next day. They are stocked per-farmhand so that they can be different for everyone (such as with backpack upgrades), however a LimitedStockMode of Global will sync the stock between players, just like a normal shop.

If LimitedStockMode is Player, then it will be shown before other items, and will not count towards the ItemCountToSell. Once a LimitedStockMode Player item is purchased, it will move to the next not-displayed LimitedStockMode Player that was stocked, and once those are out of stock it will move on to the synced item stocks.

Display shop items are always purchased one at a time - a higher stack size means it can be bought multiple times.

The data asset, located at Data/DisplayShops, consists of a string -> model lookup, where...

  • The key is the ID of the display shop.
  • The value is a model with the fields listed below.
field effect
basic info
OpenCondition (Optional) A Game State Query for determining if the display shop if is open (that is, if the items shown are purchasable or not). If not specified, it will always be open.
ClosedMessage (Optional) A Tokenizable String for what message to show if the shop is closed. Defaults to (after token parsing) "Closed.".
Currency (Optional) The currency to use for the price, with the same options as in Data/Shops. Defaults to 0 (standard gold).
cosmetic
PurchaseSound (Optional) A sound to play upon making a successful purchase. Defaults to "purchaseClick".
ItemWorldOffset (Optional) A Vector2 of how far to move the display item from the tile that has the purchase tile action. For example, Pierre's shop counter has a value of 0 -72 so that the items show on top of the counter. Defaults to 0.
stocked products
ApplyProfitMargins (Optional) Whether or not to apply profit margins by default for items in this shop. Defaults to null.
PriceModifiers (Optional) Price modifiers to apply to items in this shop. Behaves the same way as Data/Shops PriceModifiers.
PriceModifierMode (Optional) Price modifier mod for applying price modifiers to items in this shop. Behaves the same way as Data/Shops PriceModifierMode.
ItemCountToSell (Optional) The amount of items that can be sold each day.
ItemPool (Optional) The items to use when populating the shop. This list is sorted by Precedence before being used, with entries of the same precedence being shuffled together. This list consist of values with these fields:
field effect
common fields See Items for Shops for the item fields supported by display shop items.

Notes:

  • If set to an item query which returns multiple items, all of them will be valid choices for the shop.
  • Unlike other item spawn fields, ObjectDisplayName is supported for any entry (not just Object items).
DisplayOffset (Optional) The amount to offset drawing this item when shown in the display shop. This is useful for non-standard-sized items.
DisplayScale (Optional) How much to scale the item when it is shown. Defaults to 4 (just like most things in the game).
ItemBlurb (Optional) Text to show in a dialogue box before the item prompt appears.
ItemBlurbSpeaker (Optional) The NPC that will "speak" the ItemBlurb, if desired.
Precedence (Optional) The precedence for this item to be checked, with higher being sooner. Defaults to 0.

To make the display shop show in world, you need to use a new tile action: DisplayShop <displayShopId> <itemIndex>, with displayShopId being the ID of the entry in Data/DisplayShops and itemIndex being which index of the stocked items to make available (based on the corresponding ItemCountToSell value).

For example, here's how to add a new entry to Pierre's counter:

{
    "Format": "2.9.0",
    "Changes": [
        {
            "Action": "EditData",
            "Target": "Data/DisplayShops",
            "TargetField": [ "SeedShopCounter", "ItemPool" ],
            "Entries": {
                "{{ModId}}_Weeds": {
                    "ItemId": "(O)0",
                    "Price": 123,
                    "AvailableStock": 3,
                    "ItemBlurb": "wow some weeds. perfect for honey",
                    "ItemBlurbSpeaker": "Penny",
                    "Precedence": -100,
                }
            }
        }
    ]
}


Enchantment data

Enchantments have been partly de-hardcoded into a new Data/Enchantments data asset. Mods can now easily add new enchantments, including enchantments applied through the forge using a prismatic shard or a custom item ID.

However, this logic is still hardcoded:

  • Forging innate enchantments. The innate enchantments are in data, but the logic to choose which to apply is still hardcoded.
  • Forging diamonds into a weapon to fill all its weapon stat slots.
  • Several enchantments' effects when applied (though weapon buff effects are in data).

This consists of a string → model lookup, where...

  • The key is the unique string ID for the enchantment.
  • The value is a model with the fields listed below.
field effect
DisplayName A tokenizable string for the enchantment's display name, shown in tooltips. This can contain {0} for the enchantment level, if applicable.
ForgeWith (Optional) If set, this enchantment is applied to tools by forging an item with this qualified ID into it. Default none, in which case it won't be applicable through the forge.
AppliesTo (Optional) The tools or weapons to which this enchantment can be applied. Defaults to all tools/weapons.

This is specified as an array of context tag queries. The enchantment can be applied if at least one query matches.

"AppliesTo": [
    "melee_weapon, !is_scythe", // any non-scythe melee weapon
    "hoe, upgrade_level_4"      // any hoe upgraded to iridium or higher
]
EnchantmentSlot (Optional) The 'slot' this enchantment goes in. Only one enchantment per slot can normally be applied, except for the "Forge" slot. Default is "Primary".

Valid vanilla types are:

type example
Primary A normal enchantment applied through a prismatic shard.
Forge A weapon stat enchantment applied through the forge.
Transforming An item transformation enchantment applied through the forge with galaxy souls.
Innate1 and Innate2 An innate enchantment applied through the forge using a dragon tooth.
IsSecondary (Optional) Whether this is an innate enchantment applied through the forge using a dragon tooth. Default false.
IsVisible (Optional) Whether the enchantment should be shown in the tool/weapon's tooltip. Default true.
MaximumLevel (Optional) The number of times this enchantment can be applied to the same tool to upgrade the enchantment level (e.g. for weapon stat enchantments). A value of 1 means there's only one enchantment level, so it can't be upgraded by applying the enchantment again. Default 1.
EquipmentEffects (Optional) The buffs applied to the weapon when this enchantment is applied.

This consists of a list of models with the fields below. You can specify any number of entries; the first one which matches the tool will be applied.

field effect
Id A unique string ID for this entry.
MinLevel (Optional) The minimum enchantment level for which these stats apply. Default 0 (i.e. any level).
other fields See the Effects field in Data/Buffs, which is equivalent to this model.
Transformations (Optional) If EnchantmentSlot is "Transforming", this contains all valid transformations for it.

This is a dictionary of qualified item IDs, with the key being the original item, and the value being the transformed item.

Transformations to and from items besides weapons are allowed, with some caveats:

  • If the source item cannot be enchanted, the maximum level for the enchantment must be 1, or it will not work.
  • If the source item and transformed item are different C# types, then all extra item data (such as mod data, enchantments, and tool enchantments) will be lost, since an entirely new item had to be created.
advanced
CustomFields (Optional) The custom fields for this entry.
ClassName (Optional, specialized) The name of the C# class to construct within the StardewValley.Enchantments namespace. The class must be a subclass of StardewValley.Enchantments.Enchantment, and have a constructor with no arguments. For example, given a value of BottomlessEnchantment, the game will create StardewValley.Enchantments.BottomlessEnchantment instances.

This should usually be omitted, in which case the game will create a generic Enchantment instance which uses the data in Data/Enchantments for its ID.

Event changes

Added new event commands:

command description
setDrawDepthModifier <npc> <amountInTiles> Modify the draw depth of <npc> for this event, by <amountInTiles>.
setDrawDepthModifier <npc> reset Reset the draw depth modifier of <npc> for this event.
ForceBreathing <npc> false Prevent <npc> from showing a breathing animation for this event.
ForceBreathing <npc> true [breathPosX] [breathPosY] [breathRectX] [breathRectY] [breathRectWidth] [breathRectHeight] Force <npc> to show a breathing animation for this event. You can optionally override the data used for the breathing rect, with the values following the same behavior as they would if specified in the Data/Characters character data.
ForceBreathing <npc> reset Reset the forced breathing modifier of <npc> for this event.
SaveActorState <stateStoreId> <actor> <state>+ Stores the specified <actor>'s current <state>(s) into the <stateStoreId> actor state store, to be loaded later.

Any actor, both NPC and Farmer, can be specified. If all is specified, them all actors will have their state saved.

Multiple <state> values can be specified, separated by spaces. Valid <state> values include:

state type description
all Saves all vanilla state types for the specified actor.

Modded state types are not included here to make it less likely that modded state types will break existing events. For using modded state types in bulk, see the bottom of this table.

Any state starting with ! This will remove the specified state from the current selection of ones to be saved.

For example, you could specify all !movement !animation to save all state except the movement state and animation state.

position The current position of the actor.
movement The movement state of the actor, including its current speed, advancedMove data, and ignoreCollisions flag.
animation The animation state of the actor, including its facing direction, ignoreMovementAnimation flag, and (for NPCs only) its ForceBreathing values.
drawOffset Values previously specified in drawOffset and setDrawDepthModifier.
name The NPC's current display name.
portrait The NPC's current portrait.
sprite The NPC's current sprite.
shadow The NPC's current hideShadow value.
swimming The NPC's current swimming state.
Any state ending with / Specifying a state ending with / will result in all state types starting with that string to be added.

For example, specifying spacechase0.SpaceCore/ would add all states that were added by SpaceCore (assuming they were properly namespaced).

This also works with "nested namespaces", ex. spacechase0.SpaceCore/MagicalStuff/ would add all "magical stuff" states added by SpaceCore.

LoadActorStateStore <stateStoreId> Loads all actor state stored in the <stateStoreId> actor state store.
ClearSavedActorStateStore <stateStoreId> Clears the <stateStoreId> actor state store.

Fish pond changes

  • Added new fish pond translation keys:
    asset key usage
    Strings/UI PondQuery_<key>_<item ID>
    PondQuery_<key>_<attitude>
    All PondQuery_* translation keys can now be suffixed with either the qualified item ID of the fish, or the fish's general attitude based on their fish_talk_* context tag.

    For example, the 'fish are OK' message for an anchovy pond will be loaded from the first key which exists in this order: PondQuery_StatusOk_(O)129, PondQuery_StatusOk_Rude, or PondQuery_StatusOk.

  • Merged some fish pond translation keys:
    asset former key changes
    Strings/UI PondQuery_Status<status><number (0–6)>
    PondQuery_StatusRequestComplete_<fish disposition><number (0–2)>
    PondQuery_StatusRequestPending_<fish disposition><number (0–2)>
    Removed the number key suffixes using switch blocks (e.g. merged PondQuery_StatusOk<number> into PondQuery_StatusOk).
  • Coral and Sea urchin now have the fish_talk_coral context tag instead of a hardcoded _Coral translation key suffixes.

Item query changes

Added one new item query:

query effect
SEASONAL_RACCOON_SEED Get a seasonal raccoon seed for the current season.

This sets the stack size to the recommended amount based on the player's luck. When used in item spawn fields, you can set MinStack and MaxStack to override the stack size.

Item spawn field changes

  • Added new item spawn fields:
    field effect
    Enchantments (Optional) For tools and weapons, the enchantment IDs to apply (matching their IDs in Data/Enchantments). This field applies the normal enchantment rules. Default none.

    This is specified as an array, and you can repeat secondary enchantments to boost their level. For example, this applies Vampiric and Attack (level 2):

    "Enchantments": [ "Vampiric", "Attack", "Attack" ]
    

Game state query changes

Added game state queries:

query effect
PLAYER_INVENTORY_SIZE <player> <minSize> [maxSize] Whether any one of the specified player(s) inventory has at least <minSize> slots unlocked, and (if specified) less than or equal to [maxSize] slots unlocked.

Data/MapPatches - Dehardcoded map patches

The base game now has a data-driven conditional map patch system. At the beginning of each day, maps are reloaded, and then these are checked and applied.

field effect
OriginalMap The full asset name of the original map(s) that this patch should apply too. Multiple maps can be specified, separate by commas.
MapPatch The asset name of the map containing this patch.
SourceRect (Optional) The source rectangle of MapPatch to apply. If not specified, the whole map will be used.
DestinationPosition The position on OriginalMap to place the top left corner of the patch at.
MapProperties (Optional) Map properties to apply. To remove a property, the value should be null. To append or prepend to a property, use @MergeInto.
Condition (Optional) A game state query which indicates whether this entry applies. Default true.
Precedence (Optional) The order in which this entry should be checked, where higher precedences will apply over lower precedences.
advanced
CustomFields (Optional) The custom fields for this entry.

Previously hard-coded map patches that have been moved over are:

location map change ID of entry in Data/MapPatches additional notes
The Beach (including the Night Market) The bridge to the right side of the map Beach_Bridge Mostly dehardcoded, but has special logic to apply immediately for everyone rather than at the beginning of the next day.
The Beach (including the Night Market) Town shortcut to the forest Beach_CommunityUpgradeShortcut_ForestEntrance Entirely dehardcoded.

Previously, the beach map had the warps for this defined through map properties, even if you haven't unlocked community shortcuts yet. Those warps are now applied through this patch's MapProperties and @MergeInto.

The Beach (including the Night Market) Town shortcut to the east side of town Beach_CommunityUpgradeShortcut_TownEntrance Entirely dehardcoded.

Previously, the beach map had the warps for this defined through map properties, even if you haven't unlocked community shortcuts yet. Those warps are now applied through this patch's MapProperties and @MergeInto.

The Beach (including the Night Market) The sign leading up to SquidFest Beach_SquidFest_Sign Entirely dehardcoded
The Beach (including the Night Market) SquidFest Beach_SquidFest Entirely dehardcoded
The Beach (including the Night Market) Day 2 of SquidFest's price increase on the prize sign Beach_SquidFest_PriceSignIncrease Entirely dehardcoded
Most existing hard-coded patches have not been moved over to the new system yet, but more will be added over time.

Trigger action changes

Added new trigger actions:

action effect
AddHealth <amount> Heals the local player by <amount> and plays the appropriate sound effect.
IncreaseBackpackSize <amount> Increase the backpack size of the local player by <amount>.
HoldUpItem <itemId> [message] Start animation to hold up the specified item above the player's head. If [|message] is specified, it will show that message as well.
MultiplayerGlobalMessage <translationKey> [arg1] [arg2] [arg3]... Show a global chat message in multiplayer. The translation key needs to exist in Strings/UI and must be prefixed with Chat_ within that file (meaning you would use "SomeMessage" in MultiplayerGlobalMessage and "Chat_SomeMessage" in Strings/UI). Any additional arguments after the translation key (which are parsed as tokenizable strings) will be used as substitution values using the normal notation. (ex. MultiplayerGlobalMessage "SomeMessage" "meow" "kitty cat" and "Chat_SomeMessage": "{1} goes {0}" would result in the message "kitty cat goes meow")
SetVariable <variableStoreId> <name> <value> Sets the value of the variable <name> in the <variableStoreId> store to <value>, if that variable store is writable. (For more on variables, see the relevant section in tokenizable string changes on this page.)
RemoveVariable <variableStoreId> <name> Removes the variable <name> in the <variableStoreId> store, if that variable store is writable. (For more on variables, see the relevant section in tokenizable string changes on this page.)

Tokenizable string changes

Usable in more places

Tokenizable strings are now usable in more places.

  • Game state queries
  • Trigger actions (for If, token evaluation is delayed until which value to use is checked)
  • Event commands
    • Tokens in quotes (ex. a message "[LocalizedText Strings/Events:MeowKitty]" command) will be evaluated when that command is run
    • Any token not in quotes (ex. how wedding events have [ContextualWeddingCelebrations] to inject dynamically-constructed commands based on the attendees) will be evaluated when that the event is started.
    • setSkipActions delays token evaluation until the actions are actually run, meaning any changes that occur during the event but before the player has actually pressed "skip" will be reflected in the variables used here)

Tokens are evaluated immediately, unless otherwise specified.

New tokens

The following tokens have been added:

token format output
InputArgument <argumentName> Tokenizable strings can now accept input arguments, depending on where they were called. If the input argument <argumentName> does not exist, then token evaluation fails.

Token expressions

Additionally, a new type of tokens now exists (called "expressions"), which are only usable in certain contexts. If one of these tokens is used in a place where it is not allowed, it will fail and say the token was not found. The places where expressions tokens are usable are:

  • Game state queries
  • Trigger actions
  • A few specific event commands:
    • action
    • goto, specifically for the label(s)
    • setSkipActions
token format output
Math Integer <expression>

Math Decimal <expression>

Calculates the given expression as math, using either integers (when Integer is specified) or floating point numbers (when Decimal is specified).
  • For example, [Math Integer 3 / 2] will result in 1, while [Math Decimal 3 / 2] will result in 1.5. This is because with Integer specified, each operation will remove everything after the decimal point before proceeding.
  • Valid operators include, in order of precedence:
    • Parenthesis (meaning "(" and ")") can be used to group parts of the epxression to be processed first, similar to how one would expect in a real math expression.
    • * (multiplication), / (division), and % (modulus)
    • + (addition) and - (subtraction)
Comparison <expression> Evaluates the given expression, resulting in TRUE if the expression is true, and FALSE otherwise.
  • The expression can compare numbers (whether integer or decimal), or strings.
  • Valid operators include, in order of precedence:
    • Parenthesis (meaning "(" and ")") can be used to group parts of the expression to be processed first, similar to how one would expect in a real math expression.
    • ! - negation, meaning [Comparison !TRUE] becomes FALSE, [Comparison !FALSE] becomes TRUE, and something like [Comparison !(3 >= 5)] becomes TRUE
    • < (less than), <= (less than or equal to), ≶ (greater than), >= (greater than or equal to)
    • == (equal to) and != (not equal to)
    • && ("and"), meaning [Comparison 2 > 1 && 3 == 3] becomes FALSE
    • || ("or"), meaning [Comparison 2 > 1 || 3 == 3] becomes TRUE
    • (For those who know what "logical comparison short circuiting" is, please be aware that that is currently not implemented.)
If <condition> <trueValue> [falseValue] If <condition> evalautes to TRUE, then <trueValue> is evaluated and returned. If <condition> evalutes to FALSE, then [falseValue] is evaluated and returned (if it was specified - otherwise, nothing is returned).
GameStateQuery <gsq> Evaluates the given game state query, allowing GSQ usage inside [If].
VariableExists <variableStore> <variableName> Evaluates to TRUE if <variableStore> has a variable named <variableName>, and FALSE otherwise. (For more on variable stores, see later section.)
GetVariable <variableStore> <variableName> Evaluates to the value of <variableName> in the variable store <variableStore>. If the variable does not exist, evaluation of the tokenizable string will fail. (For more on variable stores, see later section.)
GetVariableWithDefault <variableStore> <variableName> <defaultValue> Evaluates to the value of <variableName> in the variable store <variableStore>. If the variable does not exist, <defaultValue> will be returned instead. (For more on variable stores, see later section.)

Variable stores

Variables stores are a set of named variables stored in a particular location. The current available locations used as variable stores are:

variable store ID description
Global A variable store attached to the save itself.
  • Any player can read and write from this.
  • This variable store will be saved into the save file at the end of the day.
Player/<playerSpecifier> A variable store attached to a particular player.
  • <playerSpecifier> uses the same format as game state query target players, except specifiers that work for check multiple players (such as Any or All) may not be used.
  • Any player can read from this, however only the owning player can write to their variable store.
  • If a player is disconnected, their variables are saved, and will be resynced when they reconnect.
  • This variable store will be saved into the save file at the end of the day.
Local A variable store attached to a "calling context". Generally, this means it will always be reset between uses unless specifically kept, such as in the following contexts:
  • Events - A variable set in the Local variable store using the action event command will be usable later during that event.
  • Data/TriggerActions - When a trigger action has multiple actions to run, all actions will be using the same Local variable store, meaning earlier trigger actions can save data for use by later trigger actions in the same sequence.

Debug command changes

This only details some debug command changes - mainly, ones that might be useful for mod authors.

command changes
/tokens A new required parameter has been introduced as the first argument, <type>. If <type> is Text the string will be evaluated using non-expression tokens. If <type> is Expression, expression tokens will be allowed as well.
/runmacro Commented lines are now allowed - if -- is the beginning of a line, it will be ignored.
/debugaction (new) A new command for trying out tokenizable string input arguments, tokenizable string local variables, and trigger actions using them. This command maintains its own set of input arguments and a local variable store, which can be manipulated using the subcommands.
subcommand effect
/debugaction argument <name> <value> Sets the input argument <name> to <value>, which can be later used in /debugaction run and /debugaction evaluate.
/debugaction evaluate <expression> Evaluates <expression> as a tokenizable string, using input arguments and local variables previously set from this command.
/debugaction run <action> Runs <action> as a trigger action, using input arguments and local variables previously set from this command.
/debugaction clear Clears all previously set input arguments and local variables for /debugaction.

Some examples of using this command alongside /runmacro, at least at the time of writing, can be found here: https://gist.github.com/spacechase0/3ca7b2e195619a17ef9039c894cc60e4

/enchant <enchantmentId> [level] (new) Enchant the currently held item with the <enchantmentId> enchantment at level [level] (or 1 if not specified).

Changes for C# mod authors

DialogueKeyValidator

The new DialogueKeyValidator class analyses dialogue entries to detect dialogue keys which don't match one of the predefined patterns.

This is mainly meant to implement unit tests. For example, to validate all dialogue keys in a data asset:

string assetName = "Characters/Dialogues/Abigail";
var dialogues = Game1.content.Load<Dictionary<string, string>>(assetName);

var validator = new DialogueKeyValidator();
foreach ((string key, string dialogue) in dialogues)
{
    if (!validator.IsKnownFormat(assetName, key))
        Assert.Fail($"Validation failed for dialogue '{key}': key doesn't match one of the expected patterns.");
}

You can optionally extend the valid patterns by setting validator fields like MarriageDialogueKeyPatterns.

Monster changes

  • The monster data has been overhauled.
  • The new monster.Tags field contains a set of metadata tags about the monster which can be checked in Data/Monsters. It's safe to add new tags to the list for existing monster types.
  • The former monster.objectsToDrop field (a list of string object IDs) has been replaced by monster.drops (an item inventory).
  • Removed monster.getExtraDropItems(). Drops should be added in Data/Monsters instead.

Recipe changes

As part of the change for recipes using data models, Farmer.recipesCooked and Farmer.cookedRecipe(itemId) now use qualified item IDs instead of unqualified object item IDs.

SpecialItem deprecation

SpecialItem is now deprecated, and is only kept for save compatibility. All existing uses of it have been migrated to use Object instead, with the following new objects being available:

  • (O)BackpackUpgrade1
  • (O)BackpackUpgrade2
  • (O)ClubCard
  • (O)SpecialCharm
  • (O)SkullKey
  • (O)MagnifyingGlass
  • (O)DarkTalisman
  • (O)MagicInk

Tokenizable string changes

Tokenizable string parsing and evaluation has been separated into two separate stages. As a result, several places that use them now cache the parsed version (which is called ParsedStringSegment).

Any custom trigger actions, tokenizable string tokens, or event commands that want to delay tokenizable string evaluation so they can handle it themself (such as for only evaluating portions that should be used based on a condition) can attach the [DelayArgumentTokenEvaluation] attribute to their handler method. This will prevent the arguments from being evaluated before they reach your handler. (However, the handlers themselves currently still use string[] as their arguments, so this could be slightly off depending on how quotes were used.)

TokenParser.ParseText(string text, Random random, TokenParserDelegate customParser, Farmer player) is now deprecated, and TokenParser.EvaluateText(string text, TokenParserContext context) should be used instead.

Tool changes

The following were added to Tool:

member effect
virtual bool DrawEvenWhenNotUsing If true, Game1.drawTool (and therefore Tool.draw) will be called even if the Farmer.UsingTool is false. Default false.
virtual bool DrawNormalToolFrames If false, Game1.drawTool will not draw the normal "swinging" tool frames. Default true.
virtual bool DoAction(GameLocation location, Farmer who) Called when the player does a right click rather than a left click. Return true if the tool is doing something, and false otherwise.

Netfield changes

The following changes must now all be registered with ProtocolSummary before usage:

  • Additional net fields
  • Additional net types
  • Subclasses of any synced type

If this is not done, an exception will be thrown when adding netfields, or setting values of unknown types.

Instead of manually registering with ProtocolSummary or manually adding net fields using a harmony patch, everything should be registered through a new SMAPI API (coming soon) which will handle these details for you. This will ensure that if mods load in a different order on one player's computer compared to other connected players, it will not break anything.

If a farmhand's ProtocolSummary does not match the host's, they will get a protocol mismatch error upon connecting (rather than "No cabins available", or other obscure and unclear issues).

C# Event changes

C# mods can add new actor state to work with the new SaveActorState/etc. commands (previously documented in event changes above).

On Event there exists a new static function, RegisterActorStateType, which accepts the name of the new actor state type (which you should namespace with your mod ID, ex. spacechase0.SpaceCore/SomeCustomActorState), a delegate for saving the state, and a delegate for loading the state. Each delegate receives the Event instance, the relevant actor (which could be an NPC or a Farmer), and a delegate for performing the save and load to the proper place.

Enchantment changes

Besides the data-driven changes mentioned previously, Enchantments can now theoretically be put on non-Tools more easily. Most of the enchantment code has been moved from Tool to Item, and relevant functions accepting instances of the former now accept the latter. Item itself does not store enchantments though, so a custom type that supports enchantments will need to implement a virtual property so that they are properly stored.

There are also new hooks for enchantments to run: before/after taking damage, entering/leaving a location, and an update each tick.

Other breaking API changes

(This section is meant as a quick reference if you have build errors; there's no need to read through it otherwise.)

Removed or renamed types

These classes renamed in 1.7:

type migration
BaseEnchantment Renamed to Enchantment.
AxeEnchantment
BaseWeaponEnchantment
FishingRodEnchantment
HoeEnchantment
MilkPailEnchantment
PanEnchantment
PickaxeEnchantment
ShearsEnchantment
WateringCanEnchantment
Obsolete. Enchantments now target tools via data instead.

Other API changes

These class members changed in 1.7:

type member migration
BaseEnchantment
(and its subclasses)
hideEnchantmentName Replaced by EnchantmentManager.HideEnchantmentName.
hideSecondaryEnchantName Replaced by EnchantmentManager.HideSecondaryEnchantName.
GetEnchantmentFromItem(…) Replaced by EnchantmentManager.GetEnchantmentFromItem.
GetAvailableEnchantments() Removed.
  • To check whether any enchantments can be applied to a tool through the forge, use EnchantmentManager.CanForgeEnchant.
  • There's no directly equivalent method in 1.7, but you can mimic the former logic if needed.
    static List<Enchantment> GetAvailableEnchantments()
    {
        var dataAsset = DataLoader.Enchantments(Game1.content);
    
        List<Enchantment> enchantments = [];
        foreach ((string id, EnchantmentData data) in dataAsset)
        {
            if (data.ForgeWith == Object.prismaticShardQID)
                enchantments.Add(EnchantmentManager.CreateEnchantment(dataAsset, id));
        }
    
        return enchantments;
    }
    
GetAvailableEnchantmentsForItem(…) Removed.
  • To check whether any enchantments can be applied to a tool through the forge, use EnchantmentManager.CanForgeEnchant.
  • There's no directly equivalent method in 1.7, but you can mimic the former logic if needed.
    static List<Enchantment> GetAvailableEnchantmentsForItem(Item? tool, Item? item)
    {
        var dataAsset = DataLoader.Enchantments(Game1.content);
        var contextTags = tool?.GetContextTags();
    
        List<Enchantment> enchantments = [];
        foreach ((string id, EnchantmentData data) in dataAsset)
        {
            if (data.ForgeWith == Object.prismaticShardQID && (contextTags is null || EnchantmentManager.MatchesTags(contextTags, data.AppliesTo)))
                enchantments.Add(EnchantmentManager.CreateEnchantment(dataAsset, id));
        }
    
        return enchantments;
    }
    
GetName() Removed. This inconsistently returned an ID, a display name, or "Unknown Enchantment" depending on the enchantment type. Use the new Id property or the pre-existing GetDisplayName() method instead.
GetLevel() Removed. Use Level instead.
GetType() This was sometimes to identify enchantments (like enchantment.GetType() == expectedEnchantment.GetType()). That's no longer reliable, since 1.7 introduces data-based enchantments which may not have their own C# type. You should use the new enchantment.Id property instead.
ResetEnchantments() Removed. This is no longer needed since it no longer has a cached list of enchantment instances.
Furniture armchair
bed
bench
bookcase
chair
couch
decor
dresser
fireplace
lamp
longTable
other
painting
rug
sconce
table
torch
window
Removed. Replaced by the FurnitureType enum (e.g. Furniture.rug is now FurnitureType.Rug).
placementRestrictions Removed. Replaced by CanPlaceIndoors and CanPlaceOutdoors.
GreenSlime prismatic Removed. Replaced by IsPrismatic, which is just a wrapper around the monster tags field.
Monster getExtraDropItems() Removed. Drops should be added to Data/Monsters instead.

Harmony patches which can't be moved into data can target Monster.RollForDrops instead.

objectsToDrop Removed. Replaced by drops; see monster changes and Data/Monsters.
Tool GetEnchantmentLevel<T>()
GetEnchantmentOfType<T>()
hasEnchantmentOfType<T>()
Removed. Replaced by GetEnchantmentLevel(id), GetEnchantment(id), and HasEnchantment(id) respectively. All vanilla enchantments have a constant for the ID like EnchantmentIds.GalaxySoul.
Tool

ClearEnchantments()
GetMaxForges()
CanAddEnchantment(…)
CopyEnchantments(…)
GetTotalForgeLevels(…)
AddEnchantment(…)
RemoveEnchantment(…)
CanForge(…)
HasEnchantment(…)
GetEnchantment(…)
GetEnchantmentLevel(…)
Forge(…)

Removed. Enchantment functions have been moved to Item to make it easier for non-Tools to support enchantments.

NOTE: Tool is still the only type that can actually hold enchantments, since nothing else has the appropriate fields to hold them.

Tool drawTooltip<T>(…)
getExtraSpaceNeededForTooltipSpecialIcons<T>(…)
getDescriptionWidth<T>()
AddEquipmentEffects<T>()
Removed. These were only overrides of Item functions that only handled enchantments, which is now handled in Item itself.
AnimatedSprite Clone No longer virtual. It now uses a similar model that `Item` does, with a virtual `CloneNew` for creating the instance and a virtual `CloneInto` for populating it.
FarmerSprite Clone Now returns a properly cloned FarmerSprite, rather than a semi-broken AnimatedSprite based on itself.
Farmer takeDamage<T>(…) The last argument has been changed from Monster to object, to support the ability to detect damage from non-Monster sources. An example of this is BasicProjectile, which previously passed in null for that parameter.
Ring

onNewLocation(…)
onLeaveLocation(…)

These are now overrides of a function on Item. All equipped items will now have this function called.
Ring

update(…)

This now a function called updateWhenEquipped, and is an override of the same virtual function in Item. All equipped items will have this function called.
GameLocation getFish(…) A new non-optional parameter has been added: out Action onCatch.

Implementations of this method should no longer make changes to the world and instead be purely predictive. Any actual changes (ex. fish ponds changing how many fish it has, ginger island locations marking a golden walnut as collected, ...) should be within onCatch, which will be called when the item is successfully reeled in.

Name translation changes for wiki maintainers

Some in-game item and monster names were retranslated in some languages for clarity or correctness.

This list is mostly provided to help wiki maintainers update pages, so it doesn't include names which only changed capitalization, changed ' (straight apostrophe) to ’ (curly) in French, or aren't visible to vanilla players (like mine rocks).

None yet.

XNB impact

Overview

This section provides a summary of the XNB files which changed in Stardew Valley 1.7. This doesn't include new files (since they won't impact existing mods) or text changes in non-English files.

XNB mods are disproportionately affected, since...

  1. they replace the entire file;
  2. they're loaded through the MonoGame content pipeline which is less tolerant of format changes;
  3. they don't benefit from the compatibility rewrites Content Patcher provides for its content packs.

Content Patcher packs are typically unaffected (and Content Patcher will try to rewrite content packs automatically). However if a content pack replaces an entire asset instead of editing, it's more likely to be affected like an XNB mod.

Changed assets

Compatibility is broadly grouped into four categories:

  • "✘ broken": mods will remove new content or significant changes, or the mod's intended changes will no longer work. Effects may range from display bugs to crashes, depending how the game uses that specific content.
  • "✘ will remove changes": mods will remove minor changes in 1.7 (e.g. typo fixes).
  • "✓ mostly unaffected": mods will only be affected if they edit specific entries or fields.
  • Blank: no expected impact for the vast majority of mods.
content asset changes in 1.7 compatibility for pre-1.7 mods
XNB mods Content Patcher packs
Characters/Dialogue/Abigail ✘ broken ✓ mostly unaffected
Characters/Dialogue/Alex
Characters/Dialogue/Clint
Merged resort dialogue keys. ✘ broken ✓ mostly unaffected
Characters/Dialogue/Dwarf Fixed invalid dialogue keys. ✘ broken ✓ mostly unaffected
Characters/Dialogue/Elliott ✘ broken ✓ mostly unaffected
Characters/Dialogue/Evelyn Fixed invalid dialogue key. ✘ broken ✓ mostly unaffected
Characters/Dialogue/Haley Merged resort dialogue keys. ✘ broken ✓ mostly unaffected
Characters/Dialogue/Harvey Fixed invalid dialogue key. ✘ broken ✓ mostly unaffected
Characters/Dialogue/Jodi Fixed invalid dialogue key. ✘ broken ✓ mostly unaffected
Characters/Dialogue/Leah Merged resort dialogue keys. ✘ broken ✓ mostly unaffected
Characters/Dialogue/Lewis Fixed invalid dialogue key. ✘ broken ✓ mostly unaffected
Characters/Dialogue/MarriageDialogue
Characters/Dialogue/MarriageDialogue*
✘ broken ✓ mostly unaffected
Characters/Dialogue/Maru
Characters/Dialogue/Penny
Characters/Dialogue/Sam
Merged resort dialogue keys. ✘ broken ✓ mostly unaffected
Characters/Dialogue/Sebastian ✘ broken ✓ mostly unaffected
Data/Boots Overhauled format. ✘ broken ✘ broken
(until Content Patcher adds runtime migrations)
Data/Buffs Added new data field to data model. ✘ broken
Data/Buildings
Data/Characters
Added new item spawn field. ✘ broken
Data/FishPondData
Data/FruitTrees
Added new item spawn field. ✘ broken
Data/Furniture Overhauled format. ✘ broken ✘ broken
(until Content Patcher adds runtime migrations)
Data/GarbageCans
Data/GiantCrops
Added new item spawn field. ✘ broken
Data/Hats Overhauled format. ✘ broken ✘ broken
(until Content Patcher adds runtime migrations)
Data/Locations Added new item spawn field. ✘ broken
Data/Machines Added new item spawn field. ✘ broken
Data/Monsters Overhauled format. ✘ broken ✘ broken
(until Content Patcher adds runtime migrations)
Data/Movies Added new item spawn field. ✘ broken
Data/Objects ✘ broken ✓ mostly unaffected
Data/Pets
Data/Shops
Added new item spawn field. ✘ broken
Data/Weapons ✘ broken ✓ mostly unaffected
Data/WildTrees Added new item spawn field. ✘ broken
Strings/1_6_Strings Moved some translations into Strings/EnchanmentNames and Strings/Furniture.
Strings/EnchantmentNames
  • Added translations moved from Strings/1_6_Strings.
  • Renamed two keys (Auto-Hook → <samp.AutoHook, Bug Killer → BugKiller).
✘ broken ✓ mostly unaffected
Strings/Furniture Added translations for catalogue descriptions (moved from Strings/1_6_Strings). ✘ broken
Strings/Objects Moved catalogue descriptions into Strings/Furniture. ✓ mostly unaffected ✓ mostly unaffected
Strings/UI Merged some fish pond translation keys. ✘ broken ✓ mostly unaffected

Removed or moved translation keys

These translation keys were moved or removed in 1.6.16. (For changes to the content, see changed assets above.)

asset key changes
Strings/Locations SeedShop_BuyBackpack_ResponseNo Key renamed to GenericPurchase_Decline.