Difference between revisions of "Modding:Migrate to Stardew Valley 1.6"
Margotbean (talk | contribs) (i.e. = that is; e.g. = for example ;)) |
|||
Line 3,737: | Line 3,737: | ||
* {{o|from direction}}: if specified, the player must be standing in this direction relative to the shop (one of <samp>down</samp>, <samp>up</samp>, <samp>left</samp>, <samp>right</samp>, or <samp>none</samp>). Setting this to <samp>none</samp> disables the requirement. The default for most vanilla shops is <samp>down</samp>. | * {{o|from direction}}: if specified, the player must be standing in this direction relative to the shop (one of <samp>down</samp>, <samp>up</samp>, <samp>left</samp>, <samp>right</samp>, or <samp>none</samp>). Setting this to <samp>none</samp> disables the requirement. The default for most vanilla shops is <samp>down</samp>. | ||
* {{o|open time}} and {{o|close time}}: the start & end times in 26-hour format when the shop is available. Interacting with the tile outside those times does nothing. | * {{o|open time}} and {{o|close time}}: the start & end times in 26-hour format when the shop is available. Interacting with the tile outside those times does nothing. | ||
− | * {{o|owner tile area}}: if specified, the tile area which must contain one of the shop owners for the shop to be available. For a custom shop, these are defined by its <samp> | + | * {{o|owner tile area}}: if specified, the tile area which must contain one of the shop owners for the shop to be available. For a custom shop, these are defined by its <samp>Owners</samp> field. This can be specified in two forms: <samp>{{t|x}} {{t|y}}</samp> for a single tile, or <samp>{{t|x}} {{t|y}} {{t|width}} {{t|height}}</samp> for a multi-tile area. |
|- | |- | ||
| <samp>Buildings</samp> | | <samp>Buildings</samp> |
Revision as of 18:29, 1 October 2023
This page is for mod authors. Players: see Modding:Mod compatibility instead.
This page explains how to update your mods for compatibility with the next major game version (tentatively Stardew Valley 1.6.0), and documents some of the changes and new functionality. See also Migrate to SMAPI 4.0.
This describes an unreleased alpha version of the game. Things will change before it's released!
FAQs
What's changing?
Stardew Valley 1.6 makes fundamental changes to the game code to make it more extensible for mods.
Is this the modapocalypse?
Maybe. The update includes major changes to fundamental parts of the game, and SMAPI and Content Patcher can't feasibly rewrite every older mod for compatibility with some of the changes. This will break many existing mods until they're updated for the changes. However, per discussion between the game developers and modding community, we've agreed that this short-term pain is more than offset by the huge long-term improvements to modding.
How to update your mod
- Update your mod code and assets for the changes listed below (particularly Breaking changes for C# mods and Breaking changes for content packs).
- If SMAPI still says your mod is incompatible, check the TRACE messages in the log file for the reason why.
If the logs say "marked 'assume broken' in SMAPI's internal compatibility list", you can increase the Version in your content pack's manifest.json file to bypass it. - Test the mod in-game and make any other changes needed.
What's new architecturally?
.NET 6
- See also: .NET 6 under breaking changes.
For C# mod authors, Stardew Valley 1.6 updates from .NET 5 to .NET 6. See What's new in .NET 6 and What's new in C# 10 for more info, but some highlights include...
- improved performance;
- improved hot reload;
- new LINQ methods;
- record structs;
- and support for ARM64 on macOS.
What's new for items
Custom items
Overview
Stardew Valley 1.6 makes three major changes to how items work in the game:
- Each item now has a string ID (ItemId) and a globally unique string ID (QualifiedItemId). The QualifiedItemId is auto-generated by prefixing the ItemId with the item type identifier.
For legacy reasons, the ItemId for vanilla items may not be globally unique. For example, Pufferfish (object 128) and Mushroom Box (bigcraftable 128) both have ItemId: 128. They can be distinguished by their QualifiedItemId, which are (O)128 and (BC)128 respectively.
- Each item type now has an item data definition in the game code which tells the game how to handle it. C# mods can add or edit definitions. Each definition has a unique prefix which is used in the qualified item IDs. The vanilla types are bigcraftables ((BC)), boots ((B)), farmhouse flooring ((FL)), furniture ((F)), hats ((H)), objects ((O)), pants ((P)), shirts ((S)), tools ((T)), wallpaper ((WP)), and weapons ((W)).
- Custom items can now provide their own item texture, specified in a new field in the item data assets (see below). The item's ParentSheetIndex field is the index within that texture.
In other words, the four important fields for items are:
name | type | description |
---|---|---|
ItemId | string | An item key which should be globally unique, but may not be for existing vanilla items. For example, 128 (vanilla item) or Example.ModId_Watermelon (custom item). This should only have alphanumeric, underscore, and dot characters so it's safe to use in delimited fields, file names, etc. By convention this should include your mod ID or author name, like ExampleAuthor.ModId_ItemName. |
QualifiedItemId | string | A globally unique item key, like (O)128 for a vanilla item or (O)Example.ModId_Watermelon for a custom one. This is auto-generated from the TypeDefinitionId and ItemId fields. |
ParentSheetIndex | int | The item's sprite index within its spritesheet. |
TypeDefinitionId | string | The ID for the data definition which defines the item, like (O) for an object. You can use ItemRegistry.type_* constants with this field:
if (item.TypeDefinitionId == ItemRegistry.type_object)
...
|
Item references
Item references throughout the game code now use the ItemId instead of the ParentSheetIndex. Since the ItemId is identical to the index for existing vanilla items, most data assets are unaffected by this change. For example, here's from Data/NPCGiftTastes with one custom item:
"Universal_Like": "-2 -7 -26 -75 -80 72 395 613 634 635 636 637 638 724 459 Example.ModID_watermelon"
Unless otherwise noted, unqualified item IDs will produce objects. Some assets let you override that by specifying a QualifiedItemId value instead. For example, you can add (O)128
to the gift taste list to explicitly add for an object. Here's a partial list of data assets and their supported item ID formats:
data asset | item ID format |
---|---|
Data/CraftingRecipes Data/CookingRecipes |
|
Data/fruitTrees |
|
Data/NPCGiftTastes | Both supported, but only (O) items can be gifted. |
Item types
These are the item types for which custom items can added/edited:
item type | type identifier | data asset |
---|---|---|
big craftables | (BC) | Data/BigCraftables Each item can set a custom texture name in the Texture field, and sprite index in the SpriteIndex field. The default texture is TileSheets/Craftables. |
boots | (B) | Data/Boots Each item can set a custom texture name in fields 9 (item) and 7 (shoe color), and sprite index in fields 8 (item) and 5 (shoe color). The default textures are Maps/springobjects (item) and Characters/Farmer/shoeColors (shoe color). |
crops | not technically an item type | Data/Crops Each crop can set a custom texture name and sprite index. The default texture is TileSheets/crops. |
fish (in fish tanks) | not technically an item type | Data/AquariumFish Each fish can set a custom aquarium texture name in field 6, and sprite index in field 0. The default texture is LooseSprites/AquariumFish. |
furniture | (F) | Data/Furniture Each item can set a custom texture name in field 9, and sprite index in field 8. The default texture is TileSheets/furniture. |
fruit trees | not technically an item type | Data/FruitTrees Each fruit tree can set a custom texture name and sprite index. The default texture is TileSheets/fruitTrees. |
hats | (H) | Data/Hats Each item can set a custom texture name in field 7, and sprite index in field 6. The default texture is Characters/Farmer/hats. |
objects | (O) | Data/Objects Each item can set a custom texture name in the Texture field, and sprite index in the SpriteIndex field. The default texture is Maps/springobjects. |
pants | (P) | Data/pantsData Each item can set a custom texture name in the Texture field, and sprite index in the SpriteIndex field. The default texture is Characters/Farmer/pants. |
shirts | (S) | Data/shirtData Each item can set a custom texture name in the Texture field, and sprite index in the SpriteIndex field. The default texture is Characters/Farmer/shirts. Shirt textures must be exactly 256 pixels wide, divided into two halves: the left half for the shirt sprites, and the right half for any dye masks. The remaining space can be left blank if needed. sprites dye masks /-----------\ /-----------\ ┌────────────────────────────────┐ │ ┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐ │ │ │ 0 ││ 1 ││ 2 ││ a ││ b ││ c │ │ │ └───┘└───┘└───┘└───┘└───┘└───┘ │ │ ┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐ │ │ │ 3 ││ 4 ││ 5 ││ d ││ e ││ f │ │ │ └───┘└───┘└───┘└───┘└───┘└───┘ │ └────────────────────────────────┘ |
tools | (T) | Data/Tools Each item can set a custom texture name in the Texture field, and sprite index in the SpriteIndex field. The vanilla tools use the TileSheets/Tools texture. |
Wallpaper & floorpaper | (WP) and (FL) | Data/AdditionalWallpaperFlooring See format docs. |
weapons | (W) | Data/Weapons Completely overhauled into a data model. |
When resolving an unqualified item ID like 128, the game will get the first item type for which it exists in this order: object, big craftable, furniture, weapon, boots, hat, pants, shirt, tool, wallpaper, and floorpaper.
Define a custom item
You can define custom items for most vanilla item types using only Content Patcher or SMAPI's content API.
For example, this content pack adds a new Pufferchick item with a custom image, custom gift tastes, and a custom crop that produces it. Note that item references in other data assets like Data/Crops and Data/NPCGiftTastes use the item ID.
{
"Format": "2.3.0",
"Changes": [
// add item
{
"Action": "EditData",
"Target": "Data/Objects",
"Entries": {
"Example.ModId_Pufferchick": {
"Name": "Pufferchick",
"Displayname": "Pufferchick",
"Description": "An example object.",
"Type": "Seeds",
"Category": -74,
"Price": 1200,
"Texture": "Mods/Example.ModId/Objects",
"SpriteIndex": 0
}
},
// add gift tastes
{
"Action": "EditData",
"Target": "Data/NPCGiftTastes",
"TextOperations": [
{
"Operation": "Append",
"Target": ["Entries", "Universal_Love"],
"Value": "Example.ModId_Pufferchick",
"Delimiter": " " // if there are already values, add a space between them and the new one
}
]
},
// add crop (Pufferchick is both seed and produce, like coffee beans)
{
"Action": "EditData",
"Target": "Data/Crops",
"Entries": {
"Example.ModId_Pufferchick": {
"Seasons": [ "spring", "summer", "fall" ],
"DaysInPhase": [ 1, 1, 1, 1, 1 ],
"HarvestItemId": "Example.ModId_Pufferchick",
"Texture": "Mods/Example.ModId/Crops",
"SpriteIndex": 0
}
},
// add item + crop images
{
"Action": "Load",
"Target": "Mods/Example.ModId/Crops, Mods/Example.ModId/Objects",
"FromFile": "assets/{{TargetWithoutPath}}.png" // assets/Crops.png, assets/Objects.png
},
]
}
Most item data assets work just like Data/Objects. See also specific info for custom fruit trees, custom tools, and melee weapons.
Error items
In-game items with no underlying data (e.g. because you removed the mod which adds them) would previously cause issues like invisible items, errors, and crashes. This was partly mitigated by the bundled Error Handler mod.
Stardew Valley 1.6 adds comprehensive handling for such items. They'll be shown with a 🛇 sprite in inventory UIs and in-game, the name Error Item, and a description which indicates the missing item ID for troubleshooting.
For C# mods
- Compare items
-
Since Item.QualifiedItemId is globally unique, it can be used to simplify comparing items. For example:
old code new code item.ParentSheetIndex == 128 item.QualifiedItemId == "(O)128" IsNormalObjectAtParentSheetIndex(item, 128) item.QualifiedItemId == "(O)128" !item.bigCraftable && item.ParentSheetIndex == 128 item.QualifiedItemId == "(O)128" item is Boots && item.ParentSheetIndex == 505 item.QualifiedItemId == "(B)505" You can also use ItemRegistry.QualifyItemId to convert any item ID into a qualified one (if it's valid), and ItemRegistry.HasItemId to check if an item has a qualified or unqualified item ID.
Note that flavored item don't have their own ID. For example, Blueberry Wine and Wine are both (O)348. This affects flavored jellies, juices, pickles, and wines. In those cases you should still compare their separate fields like preservedParentSheetIndex (which actually contains the preserved item's ItemId, not its ParentSheetIndex).
- Construct items
- Creating items works just like before, except that you now specify the item's ItemId (not QualifiedItemId) instead of its ParentSheetIndex. For example:
new Object("128", 1); // vanilla item new Object("Example.ModId_Watermelon", 1); // custom item
You can use a new utility method to construct items from their QualifiedItemId:
Item item = ItemRegistry.Create("(B)505"); // Rubber Boots
- Define custom item types
- You can implement IItemDataDefinition for your own item type, and call ItemRegistry.AddTypeDefinition to register it. This provides all the logic needed by the game to handle the item type: where to get item data, how to draw them, etc. This is extremely specialized, and multiplayer compatibility is unknown. Most mods should add custom items within the existing types instead.
- New Is* methods
- 1.6 adds some StardewValley.Object methods to handle custom items in a generic way (and to let mods patch the logic):
method effect object.IsBar() Whether the item is a copper bar, iron bar, gold bar, iridium bar, or radioactive bar. object.IsBreakableStone() Whether the item is a stone debris item which can be broken by a pickaxe. object.IsFence() Whether the item is a fence. object.IsFruitTreeSapling() Whether the item is a fruit tree sapling. This checks the Data\fruitTrees keys, so it works with custom fruit trees too. object.IsHeldOverHead() Whether the player is shown holding up the item when it's selected in their toolbar. Default true (except for furniture). object.IsIncubator() Whether the item can incubate farm animal eggs when placed in a building. object.IsTapper() Whether the item is a tapper or heavy tapper. object.IsTeaSapling() Whether the item is a tea sapling. object.IsTwig() Whethere the item is a twig debris item. object.IsWeeds() Whether the item is a weed debris item. - Work with item metadata
-
1.6 adds an ItemRegistry API for working with the new item system. Some of the provided methods are:
method effect ItemRegistry.Create Create an item from its item ID (qualified or unqualified). If the ID doesn't match a real item, the optional allowNull parameter indicates whether to return null or an Error Item. For example: Item item = ItemRegistry.Create("(B)505"); // Rubber Boots
You can also get a specific value type instead of Item if needed. This will throw a descriptive exception if the type isn't compatible (e.g. you try to convert furniture to boots).
Boots item = ItemRegistry.Create<Boots>("(B)505"); // Rubber Boots
ItemRegistry.Exists Get whether a qualified or unqualified item ID matches an existing item. For example: bool pufferfishExist = ItemRegistry.Exists("(O)128");
ItemRegistry.IsQualifiedId Get whether the given item ID is qualified with the type prefix (like (O)128 instead of 128). ItemRegistry.QualifyItemId Get the unique qualified item ID given an unqualified or qualified one. For example: string qualifiedId = ItemRegistry.QualifyItemId("128"); // returns (O)128
ItemRegistry.GetMetadata This lets you get high-level info about an item: // get info about Rubber Boots ItemMetadata info = ItemRegistry.GetMetadata("(B)505"); // get item ID info $"The item has unqualified ID {info.LocalId}, qualified ID {info.QualifiedId}, and is defined by the {info.TypeIdentifier} item data definition."; // does the item exist in the data files? bool exists = info.Exists();
And get common parsed item data:
// get parsed info ParsedItemData data = info.GetParsedData(); $"The internal name is {data.InternalName}, translated name {data.DisplayName}, description {data.Description}, etc."; // draw an item sprite Texture2D texture = data.GetTexture(); Rectangle sourceRect = data.GetSourceRect(); spriteBatch.Draw(texture, Vector2.Zero, sourceRect, Color.White);
And create an item:
Item item = metadata.CreateItem();
And get the type definition (note that this is very specialized, and you should usually use ItemRegistry instead to benefit from its caching and optimizations):
IItemDataDefinition typeDefinition = info.GetTypeDefinition();
ItemRegistry.ResolveMetadata Equivalent to ItemRegistry.GetMetadata, except that it'll return null if the item doesn't exist. ItemRegistry.GetData Get the parsed data about an item, or null if the item doesn't exist. This is a shortcut for ItemRegistry.ResolveMetadata(id)?.GetParsedData()
; see the previous method for info on the parsed data.ItemRegistry.GetDataOrErrorItem Equivalent to ItemRegistry.GetData, except that it'll return info for an Error Item if the item doesn't exist (e.g. for drawing in inventory). ItemRegistry.GetErrorItemName Get a translated Error Item label.
Custom big craftables
You can now create/edit big craftables by editing the new Data/BigCraftables asset, which replaces the previous slash-delimited Data/BigCraftablesInformation.
Besides the format change, this adds...
- context tags (moved from the former Data/ObjectContextTags asset);
- custom fields to let framework mods support additional features.
This consists of a string → model lookup, where...
- The key is the unqualified item ID.
- The value is a model with the fields listed below.
Basic info
field | purpose |
---|---|
Name | The internal item name. |
DisplayName Description |
A tokenizable string for the item's in-game display name and description. |
Price | (Optional) The price when sold by the player. This is not the price when bought from a shop. Default 0. |
Behavior
field | purpose |
---|---|
Fragility | (Optional) How the item can be picked up. The possible values are 0 (pick up with any tool), 1 (destroyed if hit with an axe/hoe/pickaxe, or picked up with any other tool), or 2 (can't be removed once placed). Default 0. |
CanBePlacedIndoors CanBePlacedOutdoors |
(Optional) Whether the item can be placed indoors or outdoors. Default true. |
IsLamp | (Optional) Whether this is a lamp and should produce light when dark. Default false. |
Appearance
field | purpose |
---|---|
Texture | The asset name for the texture containing the item's sprite. Defaults to TileSheets/Craftables. |
SpriteIndex | The sprite's index within the Texture, where 0 is the top-left sprite. |
Context tags
field | purpose |
---|---|
ContextTags | (Optional) The custom context tags to add for this item (in addition to the tags added automatically based on the other object data). This is formatted as a list; for example:
"ContextTags": [ "light_source", "torch_item" ]
|
Advanced
field | purpose |
---|---|
CustomFields | (Optional) The custom fields for this entry. |
Custom crops
Crops are still stored in Data/Crops, but that asset has been overhauled in Stardew Valley 1.6. The slash-delimited entries are now models to simplify edits and enable new features.
This consists of a string → model lookup, where...
- The key is the unqualified item ID for the seed item.
- The value is model with the fields listed below.
field | effect | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Growth | |||||||||||||
Seasons | The seasons in which this crop can grow (any combination of spring, summer, fall, and winter). | ||||||||||||
DaysInPhase | The number of days in each visual step of growth before the crop is harvestable. Each step corresponds to a sprite in the crop's row (see SpriteIndex).
For example, a crop with | ||||||||||||
RegrowDays | (Optional) The number of days before the crop regrows after harvesting, or -1 if it can't regrow. The crop will keep the full-grown sprite (i.e. the last phase in DaysInPhase) during this time. Default -1. | ||||||||||||
IsRaised | (Optional) Whether this is a raised crop on a trellis that can't be walked through. Default false. | ||||||||||||
IsPaddyCrop | (Optional) Whether this crop can be planted near water for a unique paddy dirt texture, faster growth time, and auto-watering. For example, rice and taro are paddy crops. Default false. | ||||||||||||
Harvest | |||||||||||||
HarvestItemId | The item ID produced when this crop is harvested. | ||||||||||||
HarvestMethod | (Optional) How the crop can be harvested. This can be Grab (crop is harvested by hand) or Scythe (harvested with a scythe). Default Grab. | ||||||||||||
HarvestMinStack HarvestMaxStack |
(Optional) The minimum and maximum number of HarvestItemId to produce (before HarvestMaxIncreasePerFarmingLevel and ExtraHarvestChance are applied). A value within this range (inclusive) will be randomly chosen each time the crop is harvested. The minimum defaults to 1, and the maximum defaults to the minimum. | ||||||||||||
HarvestMinQuality HarvestMaxQuality |
(Optional) If set, the minimum and maximum quality of the harvest crop. These fields set a constraint that's applied after the quality is calculated normally, they don't affect the initial quality logic. | ||||||||||||
HarvestMaxIncreasePerFarmingLevel | (Optional) The number of extra harvests to produce per farming level. This is rounded down to the nearest integer and added to HarvestMaxStack. Defaults to 0.
For example, a value of 0.2 is equivalent to +1 max at level 5 and +2 at level 10. | ||||||||||||
ExtraHarvestChance | (Optional) The probability that harvesting the crop will produce extra harvest items, as a value between 0 (never) and 0.9 (nearly always). This is repeatedly rolled until it fails, then the number of successful rolls is added to the produced count. For example, tomatoes use 0.05. Default 0. | ||||||||||||
Appearance | |||||||||||||
Texture | The asset name for the texture (under the game's Content folder) containing the crop sprite. For example, the vanilla crops use TileSheets\crops. | ||||||||||||
SpriteIndex | (Optional) The index of this crop in the Texture, one crop per row, where 0 is the top row. Default 0. | ||||||||||||
TintColors | (Optional) The colors with which to tint the sprite when drawn (e.g. for colored flowers). A random color from the list will be chosen for each crop. See color format. Default none. | ||||||||||||
Advanced | |||||||||||||
PlantableLocationRules | (Optional) The rules to decide which locations you can plant the seed in, if applicable. The first matching rule is used. This can override location checks (e.g. crops being limited to the farm), but not built-in requirements like crops needing dirt.
This consists of a list of models with these fields:
| ||||||||||||
CustomFields | The custom fields for this entry. |
For example, this adds a custom cucumber crop (assuming you've already added custom items for cucumber seeds and cucumber):
{
"Format": "2.3.0",
"Changes": [
{
"Action": "EditData",
"Target": "Data/Crops",
"Entries": {
"Example.Id_CucumberSeeds": {
"Seasons": [ "summer" ],
"DaysInPhase": [ 1, 2, 2, 2 ], // grows in 7 days with four growing sprites
"HarvestItemId": "Example.Id_Cucumber",
"Texture": "{{InternalAssetKey: assets/crops.png}}",
"SpriteIndex": 0
}
}
}
]
}
Custom fences
You can now add or customize fences by editing the Data/Fences asset.
This consists of a string → model lookup, where the key is the unqualified item ID of the fence object, and the value is a model with these fields:
field | effect |
---|---|
Health | The health points for a fence when it's first placed, which affects how quickly it degrades. A fence loses 1/1440 points per in-game minute (roughly 0.04 points per hour or 0.5 points for a 12-hour day).
Repairing a fence sets its max health to 2 × (base_health + repair_health_adjustment), where base_health is this field's value and repair_health_adjustment is a random value between RepairHealthAdjustmentMinimum and RepairHealthAdjustmentMaximum. |
Texture | The asset name for the texture (under the game's Content folder) when the fence is placed. Use \ (or \\ in JSON) to separate name segments if needed. For example, the vanilla fences use individual tilesheets like LooseSprites\Fence1 (wood fence). |
RemovalToolIds RemovalToolTypes |
A list of tool IDs (matching the keys in Data\ToolData) or C# full type names which can be used to break the fence.
For example, this will let the player break the fence with an iridium axe and any pickaxe: "RemovalToolIds": ["IridiumAxe"],
"RemovalToolTypes": ["StardewValley.Tools.Pickaxe"]
A tool must match RemovalToolIds or RemovalToolTypes to be a valid removal tool. If both lists are null or empty, all tools can remove the fence. |
PlacementSound | The audio cue ID played when the fence is placed or repaired (e.g. axe used by Wood Fence). |
RemovalSound | (Optional) The audio cue ID played when the fence is broken or picked up by the player. Defaults to the same sound as PlacementSound. |
RemovalDebrisType | (Optional) The type of cosmetic debris particles to 'splash' from the tile when the fence is broken with a tool. The defined values are 0 (copper), 2 (iron), 4 (coal), 6 (gold), 8 (coins), 10 (iridium), 12 (wood), 14 (stone), 32 (big stone), and 34 (big wood). Default 14 (stone). |
RepairHealthAdjustmentMinimum RepairHealthAdjustmentMaximum |
(Optional) A random amount added to the Health when a fence is repaired by a player. See the Health field description. Both default to 0. |
HeldObjectDrawOffset | (Optional) When an item like a torch is placed on the fence, the pixel offset to apply to its draw position. Specified as a string in the form "<x> , <y> ". Defaults to "0, -20" if omitted.
|
LeftEndHeldObjectDrawX RightEndHeldObjectDrawX |
(Optional) The X pixel offset to apply when the fence is oriented horizontally, with only one connected fence on the right (for LeftEndHeldObjectDrawX) or left (for RightEndHeldObjectDrawX). This fully replaces the X value specified by HeldObjectDrawOffset when it's applied. Default 0. |
Custom floors (craftable) & paths
You can now add or customize craftable floors & paths by editing the Data/FloorsAndPaths asset.
This consists of a string → model lookup, where the key matches the ID field and the value is a model with these fields:
field | effect | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
ID | A key which uniquely identifies this floor/path. The ID should only contain alphanumeric/underscore/dot characters. For vanilla floors & paths, this matches the spritesheet index in the TerrainFeatures/Flooring spritesheet; for custom floors & paths, this should be prefixed with your mod ID like Example.ModId_FloorName. | ||||||||||
ItemId | The unqualified item ID for the corresponding object-type item. | ||||||||||
Texture | The asset name for the texture (under the game's Content folder) when the flooring is applied or the path is placed. Use \ (or \\ in JSON) to separate name segments if needed. For example, the vanilla tilesheet is TerrainFeatures\Flooring. | ||||||||||
Corner | The top-left pixel position for the sprite within the Texture spritesheet, specified as a model with X and Y fields. | ||||||||||
PlacementSound | The audio cue ID played when the item is applied/placed (e.g. axchop used by Wood Floor). | ||||||||||
FootstepSound | The audio cue ID played when the player steps on the tile (e.g. woodyStep used by Wood Floor). | ||||||||||
WinterTexture Corner |
(Optional) Equivalent to Texture and Corner, but applied if the current location is in winter. | ||||||||||
RemovalSound | (Optional) The audio cue ID played when the item is unapplied or picked up. Defaults to the same sound as PlacementSound. | ||||||||||
RemovalDebrisType | (Optional) The type of cosmetic debris particles to 'splash' from the tile when the item is unapplied or picked up. The defined values are 0 (copper), 2 (iron), 4 (coal), 6 (gold), 8 (coins), 10 (iridium), 12 (wood), 14 (stone), 32 (big stone), and 34 (big wood). Default 14 (stone). | ||||||||||
ShadowType | (Optional) The type of shadow to draw under the tile sprite. Default None.
The possible values are:
| ||||||||||
ConnectType | (Optional) When drawing the flooring across multiple tiles, how the flooring sprite for each tile is selected. Defaults to Default.
The possible values are:
| ||||||||||
CornerSize | (Optional) The pixel size of the decorative border when the ConnectType field is set to CornerDecorated or Default. | ||||||||||
FarmSpeedBuff | (Optional) The speed boost applied to the player, on the farm only, when they're walking on paths of this type. Negative values are ignored. Default 0.1. |
Custom machines
You can now add/edit machine logic by editing the Data/Machines asset.
This consists of a string → model lookup, where...
- The key is the qualified item ID for the item which acts as a machine (like (BC)127 for mushroom boxes).
- The value is a model with the fields listed below.
Item processing rules
field | effect | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
OutputRules | The output produced by this machine. If multiple output rules can be produced, the first available one is selected. This consists of a list of models with these fields:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AdditionalConsumedItems | (Optional) A list of extra items required before OutputRules will be checked. If specified, every listed item must be present in the player, hopper, or chest inventory (depending how the machine is being loaded).
This consists of a list of models with these fields:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AllowFairyDust | (Optional) Whether the player can add fairy dust to speed up the machine. Default true. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ReadyTimeModifiers | (Optional) Quantity modifiers applied to the produced item's processing time. The modifier conditions can use item-only tokens, which will check the input (not output) item. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ReadyTimeModifierMode | (Optional) A quantity modifier mode which indicates what to do if multiple modifiers apply at the same time. Default Stack. |
Behavior tweaks
field | effect | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
PreventTimePass | (Optional) A list of cases when the machine should be paused, so the timer on any item being produced doesn't decrement. Possible values:
| ||||||||||
AllowLoadWhenFull | (Optional) Whether the player can drop a new item into the machine before it's done processing the last one (like the crystalarium). The previous item will be lost. Default false. | ||||||||||
ClearContentsOvernightCondition | (Optional) A game state query which indicates whether the machine should be emptied overnight, so any current output will be lost. Defaults to always false. |
Audio & visuals
field | effect | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
LoadEffects WorkingEffects |
(Optional) The cosmetic effects shown when an item is loaded into the machine (for LoadEffects), or while it's processing the item (for WorkingEffects, based on the WorkingEffectChance probability). Both default to none. These consist of a list of models with these fields:
| ||||||||||||||||||||||||||||||||||||||||||
WorkingEffectChance | (Optional) The percentage chance to apply WorkingEffects each time the day starts or the in-game clock changes, as a value between 0 (never) and 1 (always). Default 0.33. | ||||||||||||||||||||||||||||||||||||||||||
LightWhileWorking | (Optional) The light emitted by the machine while it's processing an item. Default none.
This consists of a list of models with these fields:
| ||||||||||||||||||||||||||||||||||||||||||
WobbleWhileWorking | (Optional) Whether the machine sprite should bulge in & out while it's processing an item. Default false. | ||||||||||||||||||||||||||||||||||||||||||
ShowNextIndexWhileWorking ShowNextIndexWhenReady |
(Optional) Whether to show the next sprite in the machine's spritesheet while it's processing an item (ShowNextIndexWhileWorking) or ready (ShowNextIndexWhenReady). Default false. |
Player interaction messages
These only apply when the player interacts with a chest directly, instead of using a hopper or mod like Automate.
field | effect |
---|---|
InvalidItemMessage | (Optional) A tokenizable string for the message shown in a toaster notification if the player tries to input an item that isn't accepted by the machine. |
InvalidItemMessageCondition | (Optional) A game state query which indicates whether InvalidItemMessage should be shown. This can use item-related queries like ITEM_TYPE. Defaults to always true. |
InvalidCountMessage | (Optional) A tokenizable string for the message shown in a toaster notification if the input inventory doesn't contain this item, unless overridden by InvalidCountMessage under OutputRules.
This can use extra custom tokens:
|
Advanced logic
field | effect | ||||||||
---|---|---|---|---|---|---|---|---|---|
InteractMethod | (Optional) A C# method invoked when the player interacts with the machine when it doesn't have output ready to harvest.
This must be specified in the form /// <summary>The method signature for a custom <see cref="MachineData.InteractMethod"/> method.</summary>
/// <param name="machine">The machine instance for which to produce output.</param>
/// <param name="location">The location containing the machine.</param>
/// <param name="player">The player using the machine.</param>
/// <returns>Returns whether the interaction was handled.</returns>
public static bool InteractWithMachine(Object machine, GameLocation location, Farmer player);
| ||||||||
HasInput HasOutput |
(Optional) Whether to force adding the machine_input or machine_output context tags respectively. This isn't needed for most machines, since they'll be set based on the OutputRules field. Default false. | ||||||||
IsIncubator | (Optional) Whether this machine acts as an incubator when placed in a building, so players can incubate eggs in it. Default false.
This is used by the incubator and ostrich incubator. The game logic assumes there's only one such machine in each building, so this generally shouldn't be used by custom machines that can be built in a vanilla barn or coop. | ||||||||
StatsToIncrementWhenLoaded StatsToIncrementWhenHarvested |
(Optional) The game stat counters to increment when an item is placed in the machine (StatsToIncrementWhenLoaded) or when the processed output is collected (StatsToIncrementWhenHarvested). Default none. This consists of a list of models with these fields:
It's fine to use this with custom machines, but you can only increment built-in stats so it won't be applicable for most custom machines. For example, the vanilla game increments PiecesOfTrashRecycled for the recycling machine and GeodesCracked for the geode crusher. | ||||||||
CustomFields | The custom fields for this entry. |
Interacting with machines in C#
Stardew Valley 1.6 adds two Object fields for reference:
field | effect |
---|---|
lastOutputRuleId | If this is a machine, the output rule ID for the rule being processed by the machine (if any). |
lastInputItem | If this is a machine, the item that was dropped into the machine to start the current output (if any). |
And a few methods for processing items:
field | effect |
---|---|
IsMachineWorking() | Get whether the machine is currently processing an item. |
ShouldTimePassForMachine(location) | Get whether the machine should be updated in the given location. For example, this will return false for solar panels placed indoors, or outdoors on a cloudy day. |
GetMachineData() | Get the underlying machine data from Data/Machines. |
PlaceInMachine(…) | Try to place an item in the machine using the rules from Data/Machines. This returns a boolean which indicates whether the machine was successfully started. |
OutputMachine(…) | Try to set the machine output given the input item and an optional output rule to apply. Most code should call PlaceInMachine instead. |
A lot of the generic machine logic is also handled by a new MachineDataUtility class, which lets C# mods interact with machine data more directly. For example, you can check which output a machine would produce without actually updating the machine.
Custom melee weapons
Melee weapons are still stored in Data/Weapons, but that asset has been overhauled in Stardew Valley 1.6. The slash-delimited entries are now models to simplify edits and enable new features (like the new Projectiles feature).
This consists of a string → model lookup, where...
- The key is the unqualified item ID for the weapon.
- The value is model with the fields listed below.
Basic weapon info
field | effect |
---|---|
Name | The internal weapon name. |
DisplayName Description |
A tokenizable string for the translated display name & description. |
Type | The weapon type. One of 0 (stabbing sword), 1 (dagger), 2 (club or hammer), or 3 (slashing sword). |
Appearance
field | effect |
---|---|
Texture | The asset name for the spritesheet containing the weapon's sprite. |
SpriteIndex | The index within the Texture for the weapon sprite, where 0 is the top-left sprite. |
Stats
field | effect |
---|---|
MinDamage MaxDamage |
The minimum and maximum based damage caused when hitting a monster with this weapon. |
Knockback | (Optional) How far the target is pushed when hit, as a multiplier relative to a base weapon like the Rusty Sword (e.g. 1.5 for 150% of Rusty Sword's weight). Default 1. |
Speed | (Optional) How fast the player can swing the weapon. Each point of speed is worth 40ms of swing time relative to 0. This stacks with the player's weapon speed. Default 0. |
Precision | (Optional) Reduces the chance that a strike will miss. Default 0. |
Defense | (Optional) Reduces damage received by the player. Default 0. |
AreaOfEffect | (Optional) Slightly increases the area of effect. Default 0. |
CritChance | (Optional) The chance of a critical hit, as a decimal value between 0 (never) and 1 (always). Default 0.02. |
CritMultiplier | (Optional) A multiplier applied to the base damage for a critical hit. This can be a decimal value. Default 3. |
Game logic
field | effect |
---|---|
CanBeLostOnDeath | Whether the player can lose this tool when they die. Default true. |
MineBaseLevel MineMinLevel |
(Optional) The base and minimum mine level, which affect mine container drops. Both default to -1, which disables automatic mine drops. |
Advanced
field | effect | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Projectiles | (Optional) The projectiles fired when the weapon is used, which continue along their path until they hit a monster and cause damage. A separate projectile is fired for each entry in this list.
This consists of a list of models with these fields (one projectile will fire for each entry in the list):
Note that these are magic projectiles fired when the weapon is used, they're not aimed directly like slingshot projectiles. | ||||||||||||||||||||||||||||||
CustomFields | The custom fields for this entry. |
Custom movie concessions
- See also: custom movies.
You could already add/edit concessions sold in the movie theater, but conflicts were likely since each concession had an incrementing numeric ID which matched its position in the vanilla tilesheet.
Stardew Valley 1.6 addresses that with two changes:
- The Id field is now a string, so you can use a globally unique ID like ExampleAuthor.ModId_ItemName.
- You can now use a different texture with two new required fields:
field effect Texture The asset name for the texture containing the concession's sprite. SpriteIndex The index within the Texture for the concession sprite, where 0 is the top-left sprite.
For example, this content pack adds a new 'Pufferchick Pop' concession with a custom image:
{
"Format": "2.3.0",
"Changes": [
{
"Action": "EditData",
"Target": "Data/Concessions",
"Entries": {
"Example.ModId_PufferchickPop": {
"Id": "Example.ModId_PufferchickPop", // must specify ID again when creating a new entry
"Name": "PufferchickPop",
"DisplayName": "Pufferchick Pop",
"Description": "A cute cake pop shaped like a pufferchick.",
"Price": 25,
"Texture": "{{InternalAssetKey: assets/pufferchick-pop.png}}" // an image in your content pack
"SpriteIndex": 0
}
}
}
]
}
Custom museum donations & rewards
You can now add/edit the items which the museum accepts in donation and gives back in rewards through the new Data/MuseumRewards data asset.
Format
The data asset consists of a string → model lookup, where...
- The key is a unique identifier for the reward group. The ID should only contain alphanumeric/underscore/dot characters. For custom reward entries, this should be prefixed with your mod ID like Example.ModId_RewardName.
- The value is a model with the fields listed below.
field | effect | ||||||
---|---|---|---|---|---|---|---|
TargetContextTags | The items that must be donated to complete this reward group. The player must fulfill every entry in the list to unlock the reward. This consists of a list of models with these fields:
For example, an entry with the tag forage_item and count 2 will require donating any two forage items. Special case: an entry with the exact values | ||||||
FlagOnCompletion | (Optional if RewardItemIsSpecial is true) Whether to add the ID value to the player's received mail. This is used to track whether the player has collected the reward, and should almost always be true. If this is omitted and RewardItemIsSpecial is false, the player will be able collect the reward infinite times. Default false.
After the reward is collected, you can check this value using the HasFlag condition in Content Patcher. | ||||||
RewardEventSeenFlag | (Optional) The ID to add to the player's event-seen list when the reward is collected. (You must still specify FlagOnCompletion or RewardItemIsSpecial either way.)
After the reward is collected, you can check this value using the HasSeenEvent condition in Content Patcher. | ||||||
RewardItemId | (Optional) The qualified item ID for the item given to the player when they donate all required items for this group. There's no reward item if omitted. | ||||||
RewardItemCount | (Optional) The stack size for the RewardItemId (if the item supports stacking). Default 1. | ||||||
RewardItemIsSpecial | (Optional) Whether to mark the RewardItemId as a special permanent item, which can't be destroyed/dropped and can only be collected once. Default false. | ||||||
RewardItemIsRecipe | (Optional) Whether to give the player a cooking/crafting recipe which produces the RewardItemId, instead of the item itself. Ignored if the item type can't be cooked/crafted (i.e. non-object-type items). Default false. | ||||||
RewardMail | (Optional) A mail ID to add to the player's mailbox tomorrow. | ||||||
CustomFields | The custom fields for this entry. |
For example, this content pack adds two rewards, one in form of a mail, the other a machine :
{
"Format": "1.28.0",
"Changes": [
{
"Action": "EditData",
"Target": "Data/MuseumRewards",
"Entries": {
//Send a mail when a specific item is donated
"Example.ModId_ShinyArtifact": {
"TargetContextTags": [
{
"Tag": "id_example.modid_shinyartifact",//The unique context tag identifying the item
"Count": 1
},
],
"FlagOnCompletion": true,
"RewardMail": "Example.ModId_ShinyArtifact"
},
//Gives a machine as reward when 18 minerals are donated.
"Example.ModId_18MineralItems": {
"TargetContextTags": [
{
"Tag": "item_type_minerals",
"Count": 18
},
],
"RewardItemId": "(BC)Example.ModId_SuperMachine",
"RewardItemCount": 1,
"FlagOnCompletion": true,
},
},
}
]
}
The mail entry would then be added to mail data using the same key. See Custom Items and Custom Machines to add the items themselves.
Achievements
The A Complete Collection achievement is automatically adjusted to require any custom donations added too. This is based on the number of donated items though, so removing custom donations later may incorrectly mark the museum complete (since you may have donated enough items to meet the total required).
Custom fruit trees
Data format
You can now add custom fruit trees by editing the revamped Data/fruitTrees asset. This consists of a string → model lookup, where...
- The key is the unqualified item ID for the sapling item in Data/Objects.
- The value is a model with the fields listed below.
field | effect | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DisplayName | A tokenizable string for the tree's display name. This should return a display name without 'tree' (like Cherry for a cherry tree). This is used in UI messages like "Your <display name> tree wasn't able to grow last night". | ||||||||||||
Seasons | The seasons in which the fruit tree bears fruit. This consists of an array of season names (any combination of spring, summer, fall, or winter).
Note: the previous 'island' season value is no longer valid. Using summer is equivalent to how it worked before (since we now have per-location seasons). | ||||||||||||
Fruit | The fruit items to add to the tree each day while the tree is in-season. The first matching fruit (if any) is selected each day.
This consists of a list of models with these fields:
| ||||||||||||
Texture | The asset name for the texture under the game's Content folder. Use \ (or \\ in JSON) to separate name segments if needed. For example, vanilla fruit trees use TileSheets\fruitTrees. | ||||||||||||
TextureSpriteRow | The tree's row index in the Texture spritesheet (e.g. 0 for the first tree, 1 for the second tree, etc). | ||||||||||||
PlantableLocationRules | (Optional) The rules to decide which locations you can plant the sapling in, if applicable. The first matching rule is used. This can override location checks (e.g. crops being limited to the farm), but not built-in requirements like crops needing dirt.
This consists of a list of models with these fields:
| ||||||||||||
CustomFields | The custom fields for this entry. |
For example, this content pack adds a custom fruit tree, including custom items for the sapling and fruit:
{
"Format": "2.3.0",
"Changes": [
// add fruit + sapling items
// note: sapling must have an edibility under 0 (usually -300) to be plantable
{
"Action": "EditData",
"Target": "Data/Objects",
"Entries": {
"Example.ModId_Pufferfruit": {
"Name": "Pufferfruit",
"DisplayName": "Pufferfruit",
"Description": "An example fruit item.",
"Type": "Basic",
"Category": -6,
"Price": 1200,
"Texture": "Mods/Example.ModId/Objects",
"SpriteIndex": 0
},
"Example.ModId_Puffersapling": {
"Name": "Puffersapling",
"DisplayName": "Puffersapling",
"Description": "An example tree sapling.",
"Type": "Basic",
"Category": -74,
"Price": 1200,
"Texture": "Mods/Example.ModId/Objects",
"SpriteIndex": 1
}
}
},
// add fruit tree
{
"Action": "EditData",
"Target": "Data/FruitTrees",
"Entries": {
"Example.ModId_Puffersapling": {
"DisplayName": "Pufferfruit",
"Seasons": [ "spring" ],
"Fruit": [
{
"Id": "Example.ModId_Pufferfruit",
"ItemId": "Example.ModId_Pufferfruit"
}
],
"Texture": "Mods/Example.ModId/FruitTrees",
"TextureSpriteRow": 0
}
}
},
// add images
{
"Action": "Load",
"Target": "Mods/Example.ModId/FruitTrees, Mods/Example.ModId/Objects",
"FromFile": "assets/{{TargetWithoutPath}}.png" // assets/FruitTrees.png, assets/Objects.png
},
]
}
The fruit trees can then be added to the game by giving the player a sapling item in the usual ways (e.g. from a shop).
Fruit items
For C# mods, the fruitsOnTree field (number of fruit on the tree) has been replaced by fruit (list of fruit items).
Spawning fruit trees
Custom trees can be added to the game in two ways:
- Spawn them on map tiles when the location is created, using the new SpawnTree: fruit
<tree ID>
tile property. This must be added on the Paths layer, which must also have tile index 34 from the paths tilesheet. - Or give the player a seed item in the usual ways (e.g. from a shop, mail letter, etc).
Custom objects
You can now create/edit objects (the main item type) by editing the new Data/Objects asset, which replaces the previous slash-delimited Data/objectInformation.
Besides the format change, this adds...
- support for custom textures;
- revamped geode drops with support for conditions, probabilities, and item queries;
- expanded food/drink buffs (e.g. set a custom buff ID, add a custom buff icon, etc);
- context tags (moved from the former Data/ObjectContextTags asset);
- custom fields to let framework mods support additional features.
This consists of a string → model lookup, where...
- The key is the unqualified item ID.
- The value is a model with the fields listed below.
Basic info
field | purpose |
---|---|
Name | The internal item name. |
DisplayName Description |
A tokenizable string for the item's in-game display name and description. |
Type | The item's general type, like <c>Arch</c> (artifact) or <c>Minerals</c>. See details at Modding:Items#Objects. |
Category | The item category. |
Price | (Optional) The price when sold by the player. This is not the price when bought from a shop. Default 0. |
Appearance
field | purpose |
---|---|
Texture | The asset name for the texture containing the item's sprite. Defaults to Maps/springobjects. |
SpriteIndex | The sprite's index within the Texture, where 0 is the top-left sprite. |
Edibility
field | purpose | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Edibility | (Optional) A numeric value that determines how much energy (edibility × 2.5) and health (edibility × 1.125) is restored when this item is eaten. An item with an edibility of -300 can't be eaten, values from -299 to -1 reduce health and energy, and zero can be eaten but doesn't change health/energy. Default -300. | ||||||||||||||||||
IsDrink | (Optional) Whether to drink the item instead of eating it. Default false. | ||||||||||||||||||
Buff | (Optional) The buff to apply to the player when this item is eaten, if any. Default none.
This consists of a model with these fields:
|
Geodes & artifact spots
field | purpose | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
GeodeDrops GeodeDropsDefaultItems |
(Optional) The items that can be dropped when breaking open this item as a geode. Specifying either or both fields automatically enables geode behavior for this item.
You can specify one or both fields:
If both fields are specified, each geode will choose between them with an equal 50% chance. If GeodeDrops is specified but no entries match, the geode will use the GeodeDropsDefaultItems regardless of whether it's true. | ||||||||||
ArtifactSpotChances | (Optional) If this is an artifact (i.e. the Type field is Arch), the chance that it can be found by digging artifact spots in each location.
This consists of a string → model lookup, where:
|
Context tags
field | purpose |
---|---|
ContextTags | (Optional) The custom context tags to add for this item (in addition to the tags added automatically based on the other object data). This is formatted as a list; for example:
"ContextTags": [ "color_yellow", "fish_ocean", "fish_upright", "season_summer" ]
|
Advanced
field | purpose |
---|---|
CustomFields | (Optional) The custom fields for this entry. |
Custom pants
You can now create/edit pants by editing the new Data/Pants asset, which replaces Data/clothingInformation. This consists of a string → model lookup, where...
- The key is the unqualified item ID.
- The value is a model with the fields listed below.
Basic pants data
field | purpose |
---|---|
Name | (Optional) The internal name for the item. Default Pants. |
DisplayName Description |
(Optional) A tokenizable string for the item's in-game display name and description. Defaults to the generic pants text (Pants and A wearable pair of pants). |
Price | (Optional) The default price when the item is sold to the player in a shop. Default 50. |
Appearance
field | purpose |
---|---|
Texture | The asset name for the texture containing the pants' sprite. Defaults to Characters/Farmer/pants. |
SpriteIndex | The pants' sprite index within the Texture, where 0 is the top-left set. |
DefaultColor | (Optional) The dye color to apply to the sprite when the player hasn't dyed it yet, if any. See color format. Default 255 235 203 (which matches the color of the cloth item). |
CanBeDyed | (Optional) Whether the player can dye these pants. Default false. |
IsPrismatic | (Optional) Whether the pants continuously shift colors. This overrides DefaultColor and CanBeDyed if set. Default false. |
Other
field | purpose |
---|---|
CanChooseDuringCharacterCustomization | (Optional) Whether these pants can be selected on the character customization screen (e.g. when creating a character). Default false. |
CustomFields | The custom fields for this entry. |
Custom shirts
You can now create/edit shirts by editing the new Data/Shirts asset, which replaces Data/clothingInformation. This consists of a string → model lookup, where...
- The key is the unqualified item ID.
- The value is a model with the fields listed below.
Basic shirt data
field | purpose |
---|---|
Name | (Optional) The internal name for the item. Default Shirt. |
DisplayName Description |
(Optional) A tokenizable string for the item's in-game display name and description. Defaults to the generic shirt text (Shirt and A wearable shirt). |
Price | (Optional) The default price when the item is sold to the player in a shop. Default 50. |
Appearance
field | purpose |
---|---|
Texture | The asset name for the texture containing the shirt's sprite. Defaults to Characters/Farmer/shirts. |
SpriteIndex | The shirt's sprite index within the Texture, where 0 is the top-left set. |
DefaultColor | (Optional) The dye color to apply to the sprite when the player hasn't dyed it yet, if any. See color format. Default none. |
CanBeDyed | (Optional) Whether the player can dye this shirt. Default false. |
IsPrismatic | (Optional) Whether the shirt continuously shifts colors. This overrides DefaultColor and CanBeDyed if set. Default false. |
HasSleeves | (Optional) Whether to draw shirt sleeves. Default true. |
Other
field | purpose |
---|---|
CanChooseDuringCharacterCustomization | (Optional) Whether this shirt can be selected on the character customization screen (e.g. when creating a character). Default false. |
CustomFields | The custom fields for this entry. |
Custom tools
You can now create/edit tools by editing the new Data/Tools asset. This consists of a string → model lookup, where...
- The key is the unqualified item ID.
- The value is a model with the fields listed below.
Basic tool data
field | purpose |
---|---|
ClassName | The name of the C# class to construct within the StardewValley.Tools namespace. The class must be a subclass of StardewValley.Tool, and have a constructor with no arguments. For example, given a value of Axe, the game will create StardewValley.Tools.Axe instances.
The main values are:
|
Name | The internal name to set for the tool item. |
DisplayName Description |
A tokenizable string for the tool's in-game display name and description. |
AttachmentSlots | (Optional) The number of attachment slots to enable on the tool. Note that only FishingRod tools have the code to render and use attachment slots. Default -1, which keeps the default value set by the tool class. |
SalePrice | (Optional) The default price when the item is sold to the player in a shop. Defaults to -1, in which case you should set the price manually in shops. |
CustomFields | The custom fields for this entry. |
Appearance
Note that drawing the tool correctly in the world (ie, while the player is trying to use it) probably still needs custom code.
field | purpose |
---|---|
Texture | The asset name for the texture containing the tool's sprite. |
SpriteIndex | The tool's sprite index within the Texture, where 0 is the top row. |
MenuSpriteIndex | (Optional) The sprite index within the Texture for the item icon. Defaults to SpriteIndex. |
Upgrades
field | purpose | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
UpgradeLevel | (Optional) The tool upgrade level. Default -1, which keeps the default value set by the tool class. | |||||||||||||||
ApplyUpgradeLevelToDisplayName | (Optional) Whether to adjust the DisplayName for the usual upgrade levels. For example, the display name for a level one Axe changes to 'Copper Axe'. Default false.
The display name format in English is:
| |||||||||||||||
ConventionalUpgradeFrom | (Optional) If set, prepends an upgrade for the given tool ID to the UpgradeFrom field. This applies these rules (based on the UpgradeLevel field, not the upgrade level of the specified tool ID):
For example, Iridium Axe specifies this value: "ConventionalUpgradeFrom": "(T)GoldAxe"
| |||||||||||||||
UpgradeFrom | (Optional) The requirements to buy this tool from Clint's blacksmith tool upgrade shop. If you specify multiple entries, the first one which matches will be applied.
This consists of a list of models with these fields:
For example, these are equivalent to the Steel Axe's upgrade settings: "UpgradeFrom": [
{
"RequireToolId": "(T)CopperAxe",
"Price": 5000,
"TradeItemId": "(O)335", // Iron Bar
"TradeItemAmount": 5
}
]
If you want the tool to always be available, you can just omit the conditions. For example: "UpgradeFrom": [
{
"Price": 5000
}
]
Note that Clint needs a few days to smith the new tool. If you want to sell the tool directly, add it to a regular shop instead. |
Game logic
field | purpose |
---|---|
CanBeLostOnDeath | Whether the player can lose this tool when they die. Default false. |
Extensibility
field | purpose |
---|---|
ModData | (Optional) The mod data values to set when the tool is created, accessible in C# code via the tool.modData dictionary. For example:
"ModData": {
"PowerLevel": 9000
}
|
SetProperties | (Optional) Set the value of arbitrary properties on the tool class. For example, this would disable the tool animation and require no stamina:
"SetProperties": {
"InstantUse": true,
"IsEfficient": true
}
|
Custom wild trees
Data format
You can now create/edit wild trees by editing the Data/WildTrees asset.
This consists of a string → model lookup, where...
- The asset key is the unique tree type identifier. The vanilla tree IDs are 1 (oak), 2 (maple), 3 (pine), 6 (palm), 7 (mushroom), and 8 (mahogany). For custom trees, this should be prefixed with your mod ID like Example.ModId_TreeType. This should only contain alphanumeric/underscore/dot characters.
- The asset value is a model with thee fields listed below.
field | effect | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Textures | The texture to use as the tree's spritesheet in-game. If multiple textures are listed, the first matching one is used.
This consists of a list of models with these fields:
| ||||||||||||||||
SeedItemId | (Optional) The qualified item ID for the seed item. If omitted, the tree can't be planted and SeedChance will be ignored. | ||||||||||||||||
SeedPlantable | (Optional) Whether the seed can be planted by the player. If this is false, it can only be spawned automatically via map properties. Default true. | ||||||||||||||||
GrowthChance | (Optional) The probability each day that the tree will grow to the next stage without tree fertilizer, as a value from 0 (will never grow) to 1 (will grow every day). Defaults to 0.2 (20% chance). | ||||||||||||||||
FertilizedGrowthChance | (Optional) Equivalent to GrowthChance, but with tree fertilizer. Defaults to 1 (100% chance). | ||||||||||||||||
SeedChance | (Optional) The probability each day that the tree will produce a seed that will drop when the tree is shaken, as a value from 0 (never) to 1 (always). Default 0.05 (5% chance). | ||||||||||||||||
SeedOnChopChance | (Optional) The probability that a seed will drop when the player chops down the tree, as a value from 0 (never) to 1 (always). Default 0.75 (75% chance). | ||||||||||||||||
DropWoodOnChop | (Optional) Whether to drop wood when the player chops down the tree. Default true. | ||||||||||||||||
DropHardwoodOnLumberChop | (Optional) Whether to drop hardwood when the player chops down the tree, if they have the Lumberjack profession. Default true. | ||||||||||||||||
IsLeafy | (Optional) Whether shaking or chopping the tree causes cosmetic leaves to drop from tree and produces a leaf rustle sound. When a leaf drops, the game will use one of the four leaf sprites in the tree's spritesheet in the slot left of the stump sprite. Default true. | ||||||||||||||||
IsLeafyInWinter | (Optional) Whether IsLeafy also applies in winter. Default false. | ||||||||||||||||
GrowsInWinter | (Optional) Whether the tree can grow in winter (subject to GrowthChance or FertilizedGrowthChance). Default false. | ||||||||||||||||
IsStumpDuringWinter | (Optional) Whether the tree is reduced to a stump in winter and regrows in spring, like the vanilla mushroom tree. Default false. | ||||||||||||||||
AllowWoodpeckers | (Optional) Whether woodpeckers can spawn on the tree. Default true. | ||||||||||||||||
UseAlternateSpriteWhenNotShaken UseAlternateSpriteWhenSeedReady |
(Optional) Whether to render a different tree sprite when the player hasn't shaken it on that day (UseAlternateSpriteWhenNotShaken) or it has a seed ready (UseAlternateSpriteWhenSeedReady). If either field is true, the tree spritesheet must be double-width with the alternate textures on the right. If both are true, the same alternate sprites are used for both. Default false. | ||||||||||||||||
DebrisColor | (Optional) The color of the cosmetic wood chips when chopping the tree. This can be...
Defaults to 12 (brown/woody). | ||||||||||||||||
SeedDropItems | (Optional) When a seed is dropped subject to SeedChance, the item to drop instead of the item specified by SeedItemId. If this is empty or none match, the SeedItemId will be dropped instead.
This consists of a list of models with these fields:
| ||||||||||||||||
ChopItems | (Optional) The additional items to drop when the tree is chopped down. All matching items are dropped.
This consists of a list of models with these fields:
| ||||||||||||||||
ShakeItems | The items produced by shaking the tree when it's fully grown. This only applies the first time the tree is shaken each day. All matching items are dropped.
This consists of a list of models with these fields:
| ||||||||||||||||
TapItems | The items produced by tapping the tree. If multiple items can be produced, the first available one is selected.
This consists of a list of models with these fields:
| ||||||||||||||||
PlantableLocationRules | (Optional) The rules to decide which locations you can plant the seed in, if applicable. The first matching rule is used. This can override location checks (e.g. crops being limited to the farm), but not built-in requirements like crops needing dirt.
This consists of a list of models with these fields:
| ||||||||||||||||
CustomFields | The custom fields for this entry. |
Spawning wild trees
Custom trees can be added to the game in two ways:
- Spawn them on map tiles when the location is created, using the new SpawnTree: wild
<tree ID>
tile property. This must be added on the Paths layer, which must also have tile index 34 from the paths tilesheet. - Or give the player a seed item in the usual ways (e.g. from a shop, mail letter, etc).
Default recipes
You can now have crafting and cooking recipes that are learned automatically by setting the condition field to default. Any missing default recipes will be learned on day start.
For example, here's the chest entry from Data/CraftingRecipes:
"Chest": "388 50/Home/130/true/default/"
Global inventories
C# mods can now set a chest.GlobalInventoryId field to make it share a global inventory with every other chest having the same ID. This replaces the equivalent hardcoded logic for Junimo chests, which now just default to a "JunimoChests" global inventory ID. For example, this can be used to have multiple Junimo chest networks or make other containers share inventory.
C# mods can also use this to store items for other mod purposes, by using Game1.player.team.globalInventories or Game1.player.team.GetOrCreateGlobalInventory(id) directly.
Hats on aquarium fish
Custom fish in aquariums can now wear hats, just like vanilla sea urchins. This can be enabled by specifying a new field in Data/AquariumFish:
index | field | purpose |
---|---|---|
7 | hat position | The pixel position of the hat on the sprite, specified as an object with X and Y values.
Note: currently this is only used to check if the fish can wear a hat, and has no effect on its position. |
Context tag changes
New context tags
1.6 adds several new item context tags:
context tag | effect |
---|---|
campfire_item | Marks the item as a campfire. If the item also has the torch_item context tag, when it's placed in the world and turned on...
|
fish_pond_ignore | Prevents players from adding this fish to fish ponds, even if it would otherwise match an entry in Data/FishPondData. |
geode_crusher_ignored | Prevents breaking this item open in a geode crusher, even if the item has geode fields in Data/Objects. |
item_type_<type>
|
For an object-type item, the type value from the 'type and category' field. (Non-object items always have the exact tag item_type_ with nothing after the last underscore.) This is automatic and shouldn't be set manually. The tag is checked in a few places (e.g. the museum to check if an item is an artifact or mineral), but most of the game won't be affected. |
museum_donatable not_museum_donatable |
Set whether the item can be donated to the museum, overriding the vanilla logic. |
not_giftable | Prevents players from gifting this item to NPCs, who'll ignore the item entirely (e.g. as if you were holding a tool).
This only affects gift-giving, it doesn't affect non-gift logic like quest goals or special order objectives. If the NPC also has a reject_* dialogue for the item, the dialogue takes priority. |
not_placeable placeable |
Sets whether the item can be placed on the ground. |
prevent_loss_on_death | Indicates the item can't be lost when the player dies. |
sign_item | Marks the item as a sign, which lets player display items on it or place it on a fish pond to show the fish count. |
torch_item | Marks the item as a torch, which lets the player turn it on/off to emit light.
See also campfire_item. |
Context tags which affect machine processing:
context tag | effect |
---|---|
crystalarium_banned | When applied to a gem or mineral item, prevents players from placing it in a crystalarium. |
keg_juice keg_wine |
Allows processing the item in a keg to produce a juice or wine variant. |
preserves_jelly preserves_pickle |
Allows processing the item in a preserves jar to produce a jelly or pickled variant. |
seedmaker_banned | When applied to a seed item, prevents players from placing it in a seed maker. |
tapper_item | Marks the item as a tapper or heavy tapper. |
tapper_multiplier_<multiplier>
|
The multiplier applied to the tapper production speed. For example, 2 will make items take half their base time (i.e. each item will finish in base time/speed multiplier). Defaults to 1 if omitted. |
And informational tags which have no effect on the game logic:
context tag | effect |
---|---|
fish_legendary fish_legendary_family |
Marks the fish as a legendary fish or legendary fish family. These are purely informational; the legendary fish behavior is determined by data fields like CatchLimit or IsBossFish in Data/Locations. |
geode | (Added automatically) Marks the item as a geode item, which can be broken open at Clint's blacksmith shop or using a geode crusher. This is added automatically if the geode fields are present in Data/Objects. |
id_<item id>
|
(Added automatically) The qualified item ID, like id_(o)128. This can be used to match or exclude an item by ID using context tags. Any spaces in the ID are replaced with underscores, and single quotes are removed. |
is_machine | (Added automatically) Indicates the item has machine logic. This is added automatically based on Data/Machines. |
machine_input | (Added automatically) Whether the item is a machine which accepts items from the player. This is added automatically based on the machine's fields in Data/Machines:
|
machine_output | (Added automatically) Whether the item is a machine which produces items for the player to collect. This is added automatically based on the machine's fields in Data/Machines:
|
ItemContextTagManager class
For C# mods, 1.6 adds a new ItemContextTagManager class which simplifies working with item context tags and reduces repeated code.
This provides a few utility methods:
method | effect |
---|---|
GetBaseContextTags(id)
|
Get the base context tags for an item based on its raw data in Data/Objects or Data/BigCraftables. This doesn't include dynamic tags added that are based on instance info (like quality), which you can get using item.GetContextTags() .
|
DoesTagQueryMatch(query, tags)
|
Get whether a context tag query matches the given tags. For example, ItemContextTagManager.DoesTagQueryMatch("bone_item, !fossil_item", item.GetContextTags()) returns true if the item is a bone item but not a fossil (like the Bone Flute).
|
DoAllTagsMatch(requiredTags, actualTags) DoAnyTagsMatch(requiredTags, actualTags)
|
Get whether every (DoAllTagsMatch) or at least one (DoAnyTagsMatch</samp) required tag matches the actual item tags. This supports negated required tags like "!fossil_item" too. |
DoesTagMatch(requiredTag, actualTags)
|
Get whether a single tag matches the actual item tags. This supports negated required tags like "!fossil_item" too. |
SanitizeContextTag(tag)
|
(Specialized) Replace characters that may appear in item names so they're valid in context tags. For example, SanitizeContextTag("Sam's Boombox") returns sams_boombox.
|
Other context tag changes
- Context tags are now case-insensitive.
Inventory class
For C# mods, 1.6 adds a new Inventory class to manage a list of items. This is used for the Farmer.items and Chest.items fields. It implements IList<Item>, so most existing code should still work fine.
This has three main benefits:
- It has methods to simplify many common operations. For example:
method effect HasAny()
Get whether the inventory contains any items (ignoring empty slots). CountItemStacks()
Get the number of item stacks in the inventory (ignoring empty slots). ContainsId(id)
Get whether the inventory contains any item with the given qualified or unqualified item ID. ContainsId(id, minCount)
Get whether the inventory contains items with the given qualified or unqualified item ID, and their combined stack size is at least minCount. CountId(id)
Get the combined stack size of all items with the given qualified or unqualified item ID. GetById(id)
Get a list of items in the inventory with the given qualified or unqualified item ID. ReduceId(id, count)
Remove the given number of items matching the given qualified or unqualified item ID. This reduces the stack size for matching items until a total of count have been removed, and clears any slots which reach a stack size of zero. - Many common operations have been unified, so previously player-only methods can now be used with chests too.
- It has an internal index by item ID, so operations like
items.ContainsId("(O)128")
are much more efficient since they no longer iterate the list.
This replaces some previous methods:
game class | old code | migration |
---|---|---|
Farmer | getItemCount(id) GetTallyOfObject(id) GetTallyOfObject(id, isBigCraftable)
|
Use items.CountId(id) .
|
hasItemInInventory(id, count) hasItemInInventoryNamed(name) hasItemWithNameThatContains(name)
|
Use Items.ContainsId(id, count) .
| |
hasItemInList(list, id, count)
|
Use list.ContainsId(id, count) .
| |
areAllItemsNull()
|
Use !items.HasAny() .
| |
numberOfItemsInInventory()
|
Use items.CountItemStacks() to count all items, or Items.Count(p => p is Object) to match this method's actual behavior.
| |
consumeObject(id, count) removeItemsFromInventory(id, count)
|
Use items.ReduceId(id, count) .
| |
Object | ConsumeInventoryItem(player, id, count)
|
This was somewhat specialized and shouldn't be called by mod code, but the equivalent would be (obj.autoLoadChest?.items ?? player.items).ReduceId(id, count) .
|
GetTallyOfObject(player, id)
|
This was somewhat specialized and shouldn't be called by mod code, but the equivalent would be (obj.autoLoadChest?.items ?? player.items).CountId(id) .
|
It implements a new IInventory interface, which lets mods pass their own implementations to code which works on inventories.
Other item changes for C# mods
- Placed object changes:
- Every placed object now has a Location property set to the location which contains it. This removes location parameters from many object methods.
- Setting an object's tile position through obj.TileLocation now recalculcates its collision box automatically. (Setting it through the tileLocation net field directly won't though.)
- The obj.IsScarecrow() and GetScarecrowRadius() methods now work for non-bigcraftable objects too.
- Clothing changes:
- Clothes.clothesType is now an enum field.
- Clothing is no longer gender-specific. This renames indexInTileSheetMale to indexInTileSheet, obsoletes indexInTileSheetFemale, and converts gender-variant clothing into regular items.
- Removed unused ClothesType.ACCESSORY value.
- Farmer.pants and Farmer.shirt now store the item ID instead of the sprite index.
- In Data/TailoringRecipes, added a CraftingIdFeminine field which overrides CraftingId for female characters.
- Crop changes:
- Added Game1.cropData to read crop info without constantly reloading the Data/Crops asset.
- Removed most crop fields which only mirror the data (like harvestMethod or seasonsToGrowIn). Mods can get the info through crop.GetData() instead.
- Partly de-hardcoded fertilizer logic. Almost all fertilizer logic is now centralized into a new patchable set of HoeDirt methods (see list below). The only fertilizer logic that's still embedded elsewhere is the interaction errors in Utility.tryToPlaceItem.
- HoeDirt.fertilizer.Value is now set to null when there is no fertilizer. Both qualified and unqualified IDs should be expected.
- Removed crop.InferSeedIndex(). This was used to support old crops, which are now fixed by a save migration instead.
- Tool changes:
- Fixed various logic not handling custom tool upgrade levels.
- Other item logic:
- Simplified the constructors for many item types, particularly Object.
- Honey items now have their preserve field set to a new Honey type (instead of null).
- The Object.performObjectDropInAction method now applies the probe argument much more consistently. This only affects method calls with probe: true.
- The Item.salePrice() method now has option to get the price without profit margins.
- Added new fields & methods:
type field/method effect Crop GetHarvestMethod() Get the method used to harvest the crop (one of HarvestMethod.Grab or HarvestMethod.Scythe). IsInSeason(location) Whether the crop can grow in the location's current season (or true if crops ignore seasons in the location, like the greenhouse). HoeDirt HasFertilizer() Get whether the dirt has any fertilizer applied. CanApplyFertilizer(itemId) Get whether a player can apply the given fertilizer to this dirt. CheckApplyFertilizerRules(itemId) Get whether a player can apply the given fertilizer to this dirt, and the reason they can't if applicable. GetFertilizerSpeedBoost() Get the crop growth speed boost from fertilizers applied to this dirt. GetFertilizerWaterRetentionChance() Get the water retention chance from fertilizers applied to this dirt, as a value between 0 (no change) and 1 (100% chance of staying watered). GetFertilizerQualityBoostLevel() Get the quality boost level from fertilizers applied to this dirt, which influences the chance of producing a higher-quality crop. GetFertilizerSourceRect() Get the pixel area within the dirt spritesheet to draw for any fertilizer applied to this dirt. (This method existed before, but no longer requires the fertilizer ID argument.)
Item IsRecipe
Quality
Stack
sellToStorePrice(…)Equivalent to the previous Object fields/methods, to simplify common code and avoid needing to special-case Object items. appliesProfitMargins() Get whether this item should apply profit margins to shop prices. CanBeLostOnDeath() Get whether this item can be lost when the player dies, so it can be recovered from the item recovery service. HasTypeId(id)
HasTypeObject()
HasTypeBigCraftable()Get whether the item has the given type definition ID. These are null-safe and double as a null check: if (item.HasTypeId(ItemRegistry.type_object)) { // item is non-null and has type (O) }
HasTypeObject() and HasTypeBigCraftable() are shortcuts for passing ItemRegistry.type_object and ItemRegistry.type_bigCraftable respectively.
TryGetTempData
SetTempDataGet or set temporary item info that's not synchronized in multiplayer or written to the save file. For example, the game uses this to pass spawn options to the fishing minigame:
if (spawn.IsBossFish) fish.SetTempData(nameof(spawn.IsBossFish), true); ... fish.TryGetTempData(nameof(SpawnFishData.IsBossFish), out bool bossFish);
FishingRod CanUseBait()
CanUseTackle()
GetBait()
GetTackle()
HasMagicBait()
HasCuriosityLure()Simplifies working with the fishing rod's bait and tackle. Furniture SetPlacement
SetHeldObjectSet the furniture's position and rotation (SetPlacement) or held object (SetHeldObject). The latter will initialize the held object's tile position to match the furniture instance. These are used by the game to initialize furniture in one go. For example:
// oak table holding decorative bowl Furniture table = ItemRegistry .Create<Furniture>("(F)1120") .SetPlacement(5, 4, 0) .SetHeldObject(ItemRegistry.Create<Furniture>("(F)1364"));
FruitTree GetQuality() Get the quality of fruit currently being produced by the fruit tree. TryAddFruit() Add a fruit item to the tree based on its data. IndoorPot Water() Simplifies watering dirt in the garden pot. Object GetBoundingBox()
GetBoundingBoxAt(x, y)Get the pixel collision area for the item placed in the world. These replace the former getBoundingBox(position) method. Tool isScythe() Equivalent to the previous MeleeWeapon method, to simplify common code and avoid needing to special-case MeleeWeapon items. Tree CheckForNewTexture() Reset the tree's texture if it would change based on its data. GetMaxSizeHere Get the maximum size the tree can grow in its current position (e.g. accounting for nearby trees blocking growth). IsGrowthBlockedByNearbyTree Get whether growth is blocked because it's too close to another fully-grown tree. - Modularized Object.CheckForAction to simplify mod patches.
- Reworked Item.getOne() implementation to avoid common pitfalls. (This only affects mods with custom item classes, or which patch Item.getOne or Item._GetOneFrom.)
Other item changes
- Added per-object display names (e.g. for custom flavored items). See the ObjectDisplayName item spawn field, or object.displayNameFormat in C#.
- Item pedestals are now normal item, so you can spawn them using a mod like CJB Item Spawner to display items.
- Added optional Condition game state query field to Data/SpecialOrders.
- Item data changes:
- The display name field now exists in English too for Data/Boots, Data/Bundles, Data/CookingRecipes, Data/CraftingRecipes, Data/Furniture, Data/Hats, and Data/Weapons.
- The randomly spawned stones, twigs, and weeds have been formalized into litter. They all now have object type Litter, category -999 (Game1.litterCategory), a relevant display name/description (like Gold Stone & Break apart to obtain gold ore instead of Stone & ...), a price of 0 (not sellable), and edibility of -300 (inedible). This also adds all mine ore nodes to Data/Objects, so the game no longer creates invalid items to show their sprite. (Doing so in 1.6 will now show an Error Item sprite instead.)
- Honey items now have the honey_item context tag.
- Shirts no longer have a dynamic numeric ID range; every valid shirt is now listed in Data/Shirts.
- You can now apply a custom buff ID when the item is eaten, via Data/Objects's Buff field.
- The type field in Data/Objects is no longer checked using substring matching (e.g. the game now uses
data.Type == "Fish"
instead oftypeAndCategory.Contains("Fish")
), which may impact mods which depended on that undocumented behavior.
- Crop changes:
- Paddy crops now recheck for nearby water each day, so they'll update if you add/remove a building with water or change the map layout.
- In Data/Crops, each harvest option is now self-contained. For example, you can set HarvestMinStack without ExtraHarvestChance.
- Fish changes:
- Data/Fish is no longer translated, so there's only one Data/Fish.xnb field. Fish display names are now taken from Data/Objects.
- Added a new field (index 13) in Data/Fish, which sets whether the fish can be selected for the first-catch tutorial.
- Recipe changes in Data/CookingRecipes and Data/CraftingRecipes:
- These assets no longer have language variants.
- The display name now supports tokenizable strings.
- The display name can now be left blank to get it from the first item in the output list.
- Other item logic:
- Data/Bundles is now loaded later, so content packs can edit it reliably.
- Fixed furniture drawn over sitting players if it has no front texture.
What's new for locations & weather
Custom locations
You can now add/edit locations by editing the revamped Data/Locations asset.
Location format
The asset consists of a string → model lookup, where...
- The key is the internal name of the location to change, which will also be used as the location's Name (not DisplayName) field. This should only contain alphanumeric/underscore/dot characters, and custom locations' names should be prefixed with your mod ID like Example.ModId_LocationName. (The farm will use Farm_
<type key>
for a vanilla farm type, or Farm_<type ID>
for a custom farm type, or Farm_Standard if no type-specific entry was found.) - The value is a model with the fields listed below.
Basic info:
field effect DisplayName (Optional but strongly recommended) A tokenizable string for the translated location name. This is used anytime the location name is shown in-game for base game logic or mods. DefaultArrivalTile (Optional but strongly recommended) The default tile position where the player should be placed when they arrive in the location, if arriving from a warp that didn't specify a tile position. Default none, which usually places the player at (0, 0). ExcludeFromNpcPathfinding (Optional) Whether NPCs should ignore this location when pathfinding between locations. Default false. Creation:
field effect CreateOnLoad (Optional) If set, the location will be created automatically when the save is loaded using this data. This consists of a model with these fields:
field effect MapPath The asset name for the map to use for this location. AlwaysActive (Optional) Whether this location is always synchronized to farmhands in multiplayer, even if they're not in the location. Any location which allows building cabins must have this enabled to avoid breaking game logic. Type (Optional) The full name of the C# location class to create. This must be one of the vanilla types to avoid a crash when saving. There are too many to list here, but the most useful types are likely StardewValley.GameLocation (default value) and StardewValley.Locations.DecoratableLocation. Contents:
field effect ArtifactSpots (Optional) The items that can be found when digging artifact spots in this location. An artifact spot is selected by combining this field with the equivalent field on the Default entry, sorting by Precedence value, and then choosing the first entry whose fields match. (Artifact spot drops can also be listed in Data/Objects's Miscellaneous field; those are applied by the RANDOM_ARTIFACT_FOR_DIG_SPOT entry in DefaultArtifactSpots.)
This consists of a list of models with these fields:
field effect common fields See item spawn fields for the generic item fields supported by artifact spot drops. If set to an item query which returns multiple items, one of them will be selected at random.
Chance (Optional) The probability that the item will be dropped if the other fields match, as a decimal value between 0 (never) and 1 (always). Default 1. ApplyGenerousEnchantment (Optional) Whether to apply the 'Generous' enchantment, which adds a 50% chance of the item dropping twice. If the enchantment is applied, the item's fields are rerolled for the second drop (e.g. a new random value between MinStack and MaxStack is selected). Default true. OneDebrisPerDrop (Optional) Whether to split the dropped item stack into multiple floating debris that each have a stack size of one. For example, if the dropped item has a stack size of 3, this will spawn three separate item stacks. Default true. ContinueOnDrop (Optional) Whether to continue checking for more items to drop when this item is dropped. Default false. Precedence (Optional) The order in which this entry should be checked, where lower values are checked first. This can be a negative value. Artifact spots with the same precedence are checked in the order listed. Default 0. For consistency, vanilla artifact drops mostly use these values:
- -1000: location items which should override the global priority items (e.g. fossils on Ginger Island);
- -100: global priority items (e.g. Qi Beans);
- 0: normal items;
- 100: global fallback items (e.g. clay).
For example, a location with this field will drop 2-4 pufferfish with a 50% chance on summer days:
"ArtifactSpots": [ { "Condition": "LOCATION_SEASON Here summer", "ItemId": "(O)128", "MinStack": 2, "MaxStack": 4 } ]
FishAreas (Optional) The distinct fishing areas within the location. These can be referenced by fish via FishAreaId, and determine which fish are collected by crab pots. This consists of a string → model lookup, where the key is the fish area ID and the value consists of a list of models with these fields:
field effect Position (Optional) The tile position and size covered by this fishing area, specified as an object with X, Y, Width, and Height fields. This area will apply for crab pots placed within it, or when the fishing rod bobber lands within it. Default null (anywhere). Areas with a Position value have priority over those without.
CrabPotFishTypes (Optional) A list of fish types that can be caught by crab pots within the area. This is matched against field index 4 in Data/Fish for 'trap' (i.e. crab pot) fish. The vanilla types are freshwater and ocean. If omitted, defaults to freshwater. CrabPotJunkChance (Optional) The chance that crab pots within the area will find junk instead of a fish each time they produce a harvest. This is ignored if the player has the Mariner profession. Default 0.2 (20%). Fish (Optional) The fish that can be caught in the location. A fish is selected by combining this field with the equivalent field on the Default entry, sorting by Precedence value (and randomly shuffling entries with the same precedence), and then choosing the first entry whose fields match.
Note: the produced item ID is saved to recreate the fish later. Any item info that's not based on the item ID is ignored (like stack size, quality, flavored variants like Blueberry Wine vs Wine, and the is-recipe flag).
This consists of a list of models with these fields:
field effect common fields See item spawn fields for the generic item fields supported by forage items. This must return an Object item (or subclass of Object). If set to an item query which returns multiple items, one of them will be selected at random.
Chance (Optional) The probability that the fish will spawn if selected, as a decimal value between 0 (never) and 1 (always). Default 1. Season (Optional) If set, the specific season when the fish can be caught. This is much more efficient than using Condition, but only supports a single season. Defaults to null (all seasons). FishAreaId (Optional) If set, the fish area in which the fish can be caught (as an area ID defined under FishAreas). Defaults to null (all zones). BobberPosition (Optional) If set, the tile area within the location where the fishing rod's bobber must land to catch the fish. Default null (anywhere). PlayerPosition (Optional) If set, the tile area within the location where the player must be standing to catch the fish. Default null (anywhere). MinFishingLevel (Optional) The minimum fishing level needed for the fish to appear. Default 0. ApplyDailyLuck (Optional) Whether to add the player's daily luck to the spawn chance. This affects both the Chance field and the Data\Fish chance, if applicable. Default false. CuriosityLureBuff (Optional) The value to add to the spawn chance when the player has the Curiosity Lure equipped, if set to 0 or higher. This affects both the Chance field and the Data\Fish chance, if applicable. Default -1, which keeps the default behavior (i.e. no effect on the Chance field and a scaled boost to the Data\Fish chance). CatchLimit (Optional) The maximum number of this fish which can be caught by each player. This limit is permanent (i.e. once it's reached, that fish will never appear again). For example, legendary fish set this to one. Default -1 (no limit). IsBossFish (Optional) Whether this is a 'boss fish' catch. This shows a crowned fish sprite in the fishing minigame and gives five times normal XP, like legendary fish. RequireMagicBait (Optional) Whether the player must fish with Magic Bait for this fish to spawn. Default false. MinDistanceFromShore (Optional) The minimum distance from the nearest shore (measured in tiles) at which the fish can be caught, where zero is water directly adjacent to shore. MaxDistanceFromShore (Optional) The maximum distance from the nearest shore (measured in tiles) at which the fish can be caught, where zero is water directly adjacent to shore. Default -1 (no limit). Precedence (Optional) The order in which this entry should be checked, where lower values are checked first. This can be a negative value. Fish with the same precedence are shuffled randomly. Default 0. For consistency, vanilla fish mostly use values in these ranges:
- -1100 to -1000: global priority items (e.g. Qi Beans);
- -200 to -100: unique location items (e.g. legendary fish or secret items);
- -50 to -1: normal high-priority items;
- 0: normal items;
- 1 to 100: normal low-priority items;
- 1000+: global fallback items (e.g. trash).
IgnoreFishDataRequirements (Optional) Whether to ignore spawn requirements listed in Data/Fish, if applicable. The Data/Fish requirements are ignored regardless of this field for non-object ((O))-type items, or objects whose ID isn't listed in Data/Fish.
CanBeInherited (Optional) Whether this fish can be spawned in another location via the LOCATION_FISH item query. Default true. SetFlagOnCatch (Optional) The mail flag to set for the current player when this fish is successfully caught. Default none. ChanceModifiers (Optional) Quantity modifiers applied to the Chance value. Default none. ChanceModifierMode (Optional) quantity modifier modes which indicate what to do if multiple modifiers in the ChanceModifiers field apply at the same time. Default Stack. Forage (Optional) The forage that can spawn in the location. Notes:
- Unlike other item spawn lists, these entries aren't checked sequentially. Instead, the game...
- combines this list with any forage in the Default location entry;
- adds every forage entry whose Condition and Season match to a spawn pool;
- chooses a random number of spawn opportunities (between 1 and 4);
- for each spawn opportunity, chooses a random tile position and forage to spawn. If the spawn fails (e.g. the tile is water/occupied or the forage's Chance doesn't pass), the game will make nine other attempts with a re-randomized tile & forage before skipping this spawn opportunity.
- The stack size is ignored.
This consists of a list of models with these fields:
field effect common fields See item spawn fields for the generic item fields supported by forage items. This must return an Object ((O))-type item. If it uses an item query that returns multiple items, one will be selected at random. If it returns null or a non-Object item, the spawn attempt will be skipped (with a logged warning if the item type is invalid).
Chance (Optional) The probability that the item will spawn if selected, as a decimal value between 0 (never) and 1 (always). Default 1. Season (Optional) The specific season when the forage should apply. This is more efficient than using Condition, but only supports a single season. Defaults to null (all seasons). MinDailyWeeds
MaxDailyWeeds(Optional) The minimum and maximum number of weeds to spawn in a day, if applicable. Default 1 and 5 respectively. FirstDayWeedMultiplier (Optional) On the first day of each year, a multiplier to apply to the number of daily weeds spawned. Default 15. MinDailyForageSpawn
MaxDailyForageSpawn(Optional) The minimum and maximum number of forage to try spawning in one day, if applicable and the location has fewer than MaxSpawnedForageAtOnce forage. Default 1 and 4 respectively. MaxSpawnedForageAtOnce (Optional) The maximum number of spawned forage that can be present at once on the map before they stop spawning. Default 6. ChanceForClay (Optional) The probability that digging a tile will produce clay, as a value between 0 (never) and 1 (always). Music:
field effect Music (Optional) The music to play when the player enters the location (subject to the other fields like MusicContext). The first matching entry is used. If none match, falls back to MusicDefault.
This consists of a list of models with these fields:
field effect Id A key which uniquely identifies this entry within the list. The ID should only contain alphanumeric/underscore/dot characters. For custom entries for vanilla locations, this should be prefixed with your mod ID like Example.ModId_MusicId. Condition (Optional) A game state query which indicates whether this entry applies. Default true. Track The audio track ID to play. MusicDefault (Optional) The music to play if none of the options in Music matched. If this is null, falls back to the Music map property (if set). MusicContext (Optional) The music context for this location. The recommended values are Default or SubLocation. Default Default. Setting SubLocation has two effects:
- SubLocation has a lower priority than Default. In split-screen mode, that means if player A is at a location with a Default music context, and player B is a location with a SubLocation context, the game will choose player A's music.
- When the player leaves a location with SubLocation music, the music will be stopped unless the new location has the same music and music context set.
MusicIgnoredInRain (Optional) Whether the location music is ignored when it's raining in this location. Default false. MusicIgnoredInSpring
MusicIgnoredInSummer
MusicIgnoredInFall
MusicIgnoredInWinter(Optional) Whether the location music is ignored in the given season. Default false. MusicIgnoredInFallDebris (Optional) Whether the location music is ignored in fall during windy weather. Default false. MusicIsTownTheme (Optional) Whether to use the same behavior as Pelican Town's music: it will start playing after the day music has finished, and will continue playing while the player travels through indoor areas, but will stop when entering another outdoor area that isn't marked with the same Music and MusicIsTownTheme values. Default false. Advanced:
field effect CustomFields The custom fields for this entry. Default entry
The asset has a location with the key Default. The ArtifactSpots, Fish, and Forage fields for this entry are added to every other location's equivalent fields, so this lets you add artifact spots / fish / forage in all locations.
Custom location contexts
Vanilla contexts
- The game previously had two hardcoded location context enums: Default (for the valley) and Island (for Ginger Island). These have been replaced with data models which define the location context settings, loaded from the Data/LocationContexts asset.
- The desert is now part of a new Desert context (instead of Default). Some of the previously hardcoded desert logic (like always sunny weather) is now just part of the context data in Data/LocationContexts.
Format
Custom contexts can be created by editing the new Data/LocationContexts asset, and setting the context name in the location's LocationContext map property.
The data asset consists of a string → model lookup, where the key matches the Name field and the value is a model with these fields:
- Required fields:
-
field effect Name The unique ID for the location context. This should only contain alphanumeric/underscore/dot characters. For custom contexts, this should be prefixed with your mod ID like Example.ModId_ContextName. - Player actions:
-
field effect PlantableLocations (Optional) The internal names of the locations where crops can be planted and grown, unless overridden by planting rules in their data. AllowRainTotem (Optional) Whether a rain totem can be used to force rain in this context tomorrow. If false, using a rain totem here will show a "this item can't be used here" message instead. RainTotemAffectsContext (Optional) If set, using a rain totem here will change the weather in the given context ID. For example, rain totems in the desert change weather in the valley. MaxPassOutCost (Optional) When the player passes out (due to exhaustion or at 2am) in this context, the maximum amount of gold lost. If omitted or set to -1, uses the same value as the Default context ( 1,000g by default).
PassOutMail (Optional) When the player passes out (due to exhaustion or at 2am) in this context, the possible letter IDs to add to their mailbox (if they haven't received it before). If multiple letters are valid, one will be chosen randomly (unless one specifies SkipRandomSelection). This consists of a list of models with these fields:
field effect Mail The letter ID to add. The game will look for an existing letter ID in Data/mail in this order (where
<billed>
is Billed if they lost gold or NotBilled otherwise, and<gender>
is Female or Male):<letter id>
_<billed>
_<gender>
<letter id>
_<billed>
<letter id>
If no match is found in Data/mail, the game will send passedOut2 instead.
If the mail ID starts with passedOut, {0} in the letter text will be replaced with the gold amount lost, and it won't appear in the collections page.
MaxPassOutCost (Optional) The maximum amount of gold lost. This is applied after the context's MaxPassOutCost (i.e. the context's value is used to calculate the random amount, then this field caps the result). Defaults to unlimited. Condition (Optional) A game state query which indicates whether this entry is active. Defaults to always true. SkipRandomSelection (Optional) If true, send this mail if the Condition matches instead of choosing a random valid mail. Default false. PassOutLocations (Optional) When the player passes out (due to exhaustion or at 2am) in this context and they started the day in a different location context, the locations where they'll wake up. (If the player started the day in the same context, they'll wake up in the last bed they slept in instead.) This consists of a list of models with these fields:
field effect Location The internal location name. Position The default tile position within the location, specified as an object with X and Y fields. If the location has any bed furniture, they'll be placed in the first bed found instead. Condition (Optional) A game state query which indicates whether this entry is active. Defaults to always applied. If no locations are specified or none match, the player will wake up in their bed at home.
ReviveLocations (Optional) If the player just got knocked out in combat, the location names where they'll wake up. This consists of a list of models with these fields:
field effect Location The internal location name. Position The tile position within the location, specified as an object with X and Y fields. Condition (Optional) A game state query which indicates whether this entry is active. Defaults to always applied. If the selected location has a standard event with the exact key PlayerKilled (with no / or preconditions in the key), that event will play when the player wakes up and the game will apply the lost items or gold logic. The game won't track this event, so it'll repeat each time the player is revived. If there's no such event, the player will wake up without an event, and no items or gold will be lost.
If no locations are specified or none match, the player will wake up at Harvey's clinic.
- Season:
-
field effect SeasonOverride (Optional) The season which is always active for locations within this context (one of spring, summer, fall, or winter). For example, setting summer will make it always summer there regardless of the calendar season. If not set, the calendar season applies. - Weather:
-
field effect WeatherConditions (Optional) The weather logic to apply for locations in this context (ignored if CopyWeatherFromLocation is set). Defaults to always sunny. If multiple are specified, the first matching weather is applied. This consists of a list of models with these fields:
field effect Weather The weather ID to set. Condition (Optional) A game state query which indicates whether to apply the weather. Defaults to always applied. CopyWeatherFromLocation (Optional) The Name (i.e. unique ID) of the location context from which to inherit weather. If a passive festival is active in any location within this context, the weather is sunny for the entire context regardless of these fields.
- Music:
-
field effect DefaultMusic (Optional) The cue ID for the music to play when the player is in the location, unless overridden by a Music map property. Despite the name, this has a higher priority than the seasonal music fields below. Ignored if omitted. DefaultMusicCondition (Optional) A game state query which returns whether the DefaultMusic field should be applied (if more specific music isn't playing). Defaults to always true. DefaultMusicDelayOneScreen (Optional) When the player warps and the music changes, whether to silence the music and play the ambience (if any) until the next warp (similar to the default valley locations). Default false. SpringMusic
SummerMusic
FallMusic
WinterMusic(Optional) A list of cue IDs to play before noon in this location unless it's raining, there's a Music map property, or the context has a DefaultMusic value. If multiple values are specified, the game will play one per day in sequence. DayAmbience
NightAmbience(Optional) The cue ID for the background ambience to play when there's no music active, depending on the time of day. Both default to none. PlayRandomAmbientSounds (Optional) Whether to play random outdoor ambience sounds depending on factors like the season and time of day (e.g. birds, crickets, and mysterious groan sounds in the rain). This is unrelated to the DayAmbience and NightAmbience fields. Default true. - Advanced:
-
field effect CustomFields The custom fields for this entry.
Custom garbage cans
Format
You can now add or edit garbage cans on any map by editing the new Data/GarbageCans asset (see examples below).
The asset consists of a data model with these fields:
field effect DefaultBaseChance The probability that an item will be found when searching garbage cans, as a value between 0 (never) and 1 (always). If the probability check fails, only items that set IgnoreBaseChance can spawn. This can be overridden by the per-garbage-can BaseChance field. Default 0.2. BeforeAll
AfterAllThe items to prepend (BeforeAll) or append (AfterAll) to the GarbageCans → Items field for all garbage cans. These work exactly like the items in that field (e.g. subject to the garbage can's base chance). GarbageCans The data for individual garbage cans. This consists of a string → model lookup with these fields: field effect entry key A key which uniquely identifies this garbage can. The key should only contain alphanumeric/underscore/dot characters. For custom garbage cans, this should be prefixed with your mod ID like Example.ModId_GarbageCanId. BaseChance (Optional) If set, overrides the root DefaultBaseChance field for this garbage can. Defaults to DefaultBaseChance. Items (Optional) The items to try spawning when the player searches the garbage can. The first matching item in BeforeAll + Items + AfterAll will be spawned, and any further items will be ignored. Defaults to none. This consists of a list of models with these fields:
field effect common fields See item spawn fields for the generic item fields supported by garbage cans. If set to an item query which returns multiple items, one of them will be selected at random.
IgnoreBaseChance (Optional) Whether this item can spawn even if the BaseChance probability check didn't pass. Default false. IsMegaSuccess (Optional) Whether to treat this item as a 'mega success' if it's selected, which plays a special crit sound and bigger animation. Default false. IsDoubleMegaSuccess (Optional) Whether to treat this item as an 'double mega success' if it's selected, which plays an explosion sound and dramatic animation. Default false. AddToInventoryDirectly (Optional) Whether to add the item to the player's inventory directly, opening an item grab menu if they don't have room in their inventory. If false, the item will be dropped on the ground next to the garbage can instead. Default false. CreateMultipleDebris (Optional) Whether to split the spawned item into multiple stacks which each have a stack size of one. This has no effect if AddToInventoryDirectly is enabled. Default false. If the garbage can being searched doesn't have its own entry under GarbageCans, the game will just use the BeforeAll and AfterAll fields.
CustomFields The custom fields for this entry. Example new garbage can
You can add garbage cans using only Content Patcher or SMAPI's content API. For example, this content pack adds a new garbage can entry with the ID Example.ModId_Carpenter:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/GarbageCans", "TargetField": [ "GarbageCans" ], "Entries": { "Example.ModId_Carpenter": { "Items": [ // 25% chance of pufferfish { "ID": "Example.ModId_Pufferfish", "Condition": "RANDOM 0.25", "ItemId": "(O)128" }, // else guaranteed random House Plant item { "ID": "Example.ModId_RandomHousePlant", "ItemID": "RANDOM_ITEMS (F) @has_id_in_base_range 1376 1390" } ] } } } ] }
Then you'd place an
Action: Garbage Example.ModId_Carpenter
map tile property to mark a tile as a garbage can using this data.Example change for existing garbage can
You can edit an existing garbage cans using only Content Patcher or SMAPI's content API. For example, this content pack adds pufferfish to the Saloon garbage can, and moves it above the dish of the day.
Note that this uses TargetField to 'move into' the item list for the saloon, and then treat those items as the entry list being edited. Specifying an ID which isn't in the list will add a new entry, just like when editing a regular list asset.
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/GarbageCans", "TargetField": [ "GarbageCans", "Saloon", "Items" ], "Entries": { // 25% chance of pufferfish "Example.ModId_Pufferfish":{ "ID": "Example.ModId_Pufferfish", "Condition": "RANDOM 0.25", "ItemId": "(O)128" } }, "MoveEntries": [ { "ID": "Example.ModId_Pufferfish", "BeforeId": "Base_DishOfTheDay" } ] } ] }
Custom map actions
C# mods can now handle custom Action & TouchAction map properties by calling GameLocation.RegisterTileAction & RegisterTouchAction, and passing a callback which receives the location, map property arguments, player who activated it, and tile position.
For example, let's say you want a locked gate which needs a custom key item. You can add a regular
TouchAction Example.ModId_UnlockGate
map property (e.g. by adding it directly in the map file, or using Content Patcher's EditMap, or using the content API). Then you can just handle the logic from your C# mod:internal class ModEntry : Mod { /// <inheritdoc /> public override void Entry(IModHelper helper) { GameLocation.RegisterTouchAction("Example.ModId_UnlockGate", this.HandleUnlockGate); } private void HandleUnlockGate(GameLocation location, string[] args, Farmer player, Vector2 tile) { const string mailFlag = "Example.ModId_GateUnlocked"; const string keyId = "Example.ModId_GateKey"; // unlock gate if locked if (!player.mailReceived.Contains(mailFlag)) { if (!Game1.player.Items.ContainsId(id, count)) { Game1.activeClickableMenu = new DialogueBox("This gate is locked. I wonder where the key is?"); return; } player.removeFirstOfThisItemFromInventory(keyId); player.mailReceived.Add(mailFlag); } // apply open-gate map edit IAssetDataForMap mapHelper = this.Helper.Content.GetPatchHelper(location.map).AsMap(); mapHelper.PatchMap( this.Helper.Content.Load<Map>("assets/unlocked-gate.tmx"), targetArea: new Rectangle((int)tile.X - 1, (int)tile.Y - 1, 2, 2) ); } }
Custom map layers
You can now add any number of map layers by suffixing a vanilla layer name (i.e. Back, Buildings, Front, or AlwaysFront) with an offset. For example, Back-1 will be drawn before/under Back, and Back2 will be drawn after/over it. You can increment the number to add more layers.
This only affects layer rendering. Tile properties must still be set on the original layers.
Custom minecarts
You can now add/edit minecart destinations by editing the Data\Minecarts data asset, which consists of a data model with two relevant fields (listed below).
field effect MinecartsUnlocked A game state query which indicates whether minecarts in general are unlocked. You usually shouldn't change this value, unless you're changing the overall game progression (e.g. adding an alternative way to unlock minecart access). Destinations The destinations which the player can travel to from any minecart. This consists of a string → model lookup, where the key is a unique destination ID (only containing alphanumeric/underscore/dot characters, with custom entries prefixed with your mod ID like Example.ModId_DestinationId), and the value is a model with these fields: field effect Location The location ID for the destination. Tile The destination tile position within the location, specified as a model with X and Y fields. Direction The direction the player should face after arrival (one of down, left, right, or up). DisplayName A tokenizable string for the destination name shown in the minecart menu. You can use the location's display name with the LocationName token (like [LocationName Desert]
for the desert).Network (Optional) An arbitrary ID which groups the destination (along with any others having the same ID) into a separate network. Destinations in a network are only visible if the destination list is opened for that network via the MinecartTransport [network name]
action property. If omitted, the minecart is part of the implicit default network.Condition (Optional) A game state query which indicates whether this minecart destination is available. Defaults to always available. CustomFields The custom fields for this entry. Example
This Content Patcher content pack adds the Railroad as a minecart destination, complete with a map edit adding a decorative minecart. It is available after the Earthquake has occured and minecarts have been unlocked.
{ "Format": "2.3.0", "Changes": [ // add minecart destination { "Action": "EditData", "Target": "Data/Minecarts", "TargetField": [ "Destinations" ], "Entries": { "Railroad": { "Location": "Railroad", "Tile": { "X": 16, "Y": 39 }, "Direction": "down", "DisplayName": "[LocationName Railroad]" } }, "When": { "HasFlag": "ccBoilerRoom", "query: {{DaysPlayed}} >= 32": true } }, // add decorative minecart { "Action": "EditMap", "Target": "Maps/Railroad", "FromFile": "assets/Custom_Railroad_Minecart.tmx", "ToArea": { "X": 15, "Y": 35, "Width": 4, "Height": 5 } } ] }
Custom passive festivals
You can now add or modify passive festivals by editing the Data/PassiveFestivals asset.
(A passive festival is a festival like the Night Market. They replace a location for a period of time, the player can enter/leave them anytime, and time continues passing while at the festival.)
Data format
The Data/PassiveFestivals asset consists of a string → model lookup, where...
- The key is the unique festival ID. This should only contain alphanumeric/underscore/dot characters. For custom festivals, it should ideally be prefixed with your mod ID like Example.ModId_FestivalName.
- The value is a model with the fields listed below.
field effect DisplayName A tokenizable string for the display name shown on the calendar. Season The season when the festival becomes active. StartDay
EndDayThe days of month when the festival becomes active. StartTime The time of day when the festival opens each day. StartMessage A tokenizable string for the in-game toast notification shown when the festival begins each day. MapReplacements The locations to swap for the duration of the festival. Despite the field name, this swaps locations (e.g. as added by CustomLocations using Content Patcher), and not the location's map asset. This is specified as a string → string lookup, where the key is the original location to replace and the value is the new location. Both use the internal location name, as shown by the Debug Mode mod. For example, this swaps the Beach location with BeachNightMarket during the Night Market:
"MapReplacements": { "Beach": "BeachNightMarket" }
Condition (Optional) A game state query which indicates whether the festival is enabled (subject to the other fields like StartDay and EndDay). Defaults to always enabled. ShowOnCalendar (Optional) Whether the festival appears on the calendar, using the same iridium-star icon as the Night Market. Default true. DailySetupMethod
CleanupMethod(Optional) A C# method which applies custom logic when the day starts (DailySetupMethod) and/or overnight after the last day of the festival (CleanupMethod). These must be specified in the form
<full type name>
.<method name>
. The methods must be static, take zero arguments, and return void.CustomFields The custom fields for this entry. NPC schedules
When a passive festival is active, NPCs will check for a schedule entry in this order:
syntax summary <festival ID>
_<festival day>
Applies on the given date. The <festival day>
is relative, so 1 matches the festival StartDay.
Example: NightMarket_3 or marriage_NightMarket_3<festival ID>
Applies if there's no date-specific entry.
Example: NightMarket or marriage_NightMarketIf the NPC is married to a player, they'll add a marriage_ prefix to the keys (like marriage_
<festival ID>
_<festival day>
) and ignore any entry without the prefix.Custom weather
You can now change the weather algorithm by editing location context data, and (with a C# mod) implement custom weathers.
Fields like Game1.weather and Game1.weatherForTomorrow are now strings to support custom mod weather IDs. The change for vanilla weather has no effect on Content Patcher packs, since the new weather IDs match the ones Content Patcher was using before (i.e. Sun, Rain, Snow, Storm, and Wind). C# mods may also see a Festival weather, while Content Patcher packs will see Sun for it. The constants like Game1.weather_sunny have the new string values (with new constants like Game1.legacy_weather_sunny for the legacy values).
The base game will treat an invalid weather as sunny. C# mods can implement custom weather effects using normal SMAPI events like UpdateTicked, or by patching methods like Game1.ApplyWeatherForNewDay and Game1.populateDebrisWeatherArray.
Custom world maps
You can now change the world map shown in the game menu by editing the Data/WorldMap asset. This lets you...
- add custom maps for certain locations;
- apply texture overlays;
- add/edit tooltips;
- set real-time player marker positioning;
- etc.
The game's default map is fully defined in Data/WorldMap, including all the display text and conditional changes.
See Modding:World map for more info.
New map properties
1.6 adds several new map properties.
Warps & map positions
property explanation DefaultWarpLocation <x>
<y>
(valid in any location)The default arrival tile, used when a player or NPC is added to the location without a target tile (e.g. using debug commands like debug warp or debug eventbyid). SpouseRoomPosition <x>
<y>
(valid in farmhouse)The top-left position at which to place the spouse room. TravelingCartPosition <x>
<y>
(valid in the forest)The top-left position at which to place the Traveling Cart. This is the top-left corner of the collision box, so the roof will extend two tiles above this tile. Crops
property explanation AllowGiantCrops T If set with any non-blank value, giant crops can grow in this location (if crops are also allowed per the crop data or PlantableLocations context field). Building construction
property explanation CanBuildHere T
(valid in any outdoor location)Whether to allow constructing buildings in this location. The game will adjust automatically to account for it (e.g. Robin will let you choose where to build). See build anywhere in what's new. BuildConditions <query>
(valid in any outdoor location)If CanBuildHere is set, an optional game state query which indicates whether building is allowed currently. LooserBuildRestrictions T
(valid in any outdoor location)If set, tiles don't need to be marked Buildable T or Diggable T in their properties. Tiles can be blocked with Buildable F instead. The other restrictions still apply. ValidBuildRect <x>
<y>
<width>
<height>
(valid in any outdoor location)The tile area within the map where buildings may be placed. If omitted, buildings may be placed in any open space in the map. Other map property changes
map property changes Arch
asdf
Debris
FishRemoved (these were unused). Music Deprecated; use the music fields in Data/Locations instead. This property is only applied if the location has no music in Data/Locations. This was removed from all vanilla maps. NPCWarp
WarpNow fault-tolerant. They'll automatically ignore extra spaces, log an informative warning if parsing still fails, and continue with the next warp if possible. Stumps Now works in all locations. UniquePortrait
UniqueSpriteDeprecated; use custom NPC appearances instead. These properties will override NPC appearances. This was removed from all vanilla maps. Tile property changes
- You can now override a tile index property by setting it as a tile property.
- Added new Action tile properties:
layer property explanation Buildings Action BuildingSilo If a building covers this tile, enables silo interactions on this tile subject to the building's HayCapacity field in Data/Buildings. Buildings Action BuildingToggleAnimalDoor If a building covers this tile, opens or closes its animal door. Buildings Action Forge Opens the Forge menu. Buildings Action None Does nothing. This is used to mark the tile interactive if the click will be handled separately. Buildings Action ObeliskWarp <location name>
<x>
<y>
[whether to dismount]
Warps the player to the specified location name and position with the Obelisk animation/sound effects. Buildings Action OpenShop <shop id>
[from direction]
[open time]
[close time]
[owner tile area]
Open the shop with the given <shop id>
. All arguments besides the ID are optional:[from direction]
: if specified, the player must be standing in this direction relative to the shop (one of down, up, left, right, or none). Setting this to none disables the requirement. The default for most vanilla shops is down.[open time]
and[close time]
: the start & end times in 26-hour format when the shop is available. Interacting with the tile outside those times does nothing.[owner tile area]
: if specified, the tile area which must contain one of the shop owners for the shop to be available. For a custom shop, these are defined by its Owners field. This can be specified in two forms:<x>
<y>
for a single tile, or<x>
<y>
<width>
<height>
for a multi-tile area.
Buildings Action PlayEvent <event id>
[check preconditions]
[skip if seen]
Immediately start an event, subject to the conditions: [check preconditions]
: whether to ignore the action if the event's preconditions don't match (one of true or false). Default true.[skip if seen]
: whether to ignore the action if the player has already seen the given event. Default true.
If the event is skipped, the action is silently ignored.
For example,
Action PlayEvent 60367 false false
will replay the bus arrival event from the start of the game. - Added new TouchAction tile properties:
layer property explanation Back TouchAction PlayEvent <event id>
[check preconditions]
[skip if seen]
[fallback action]
Equivalent to Action PlayEvent. If the event is skipped, you can optionally specify another action to call instead after the other parameters, like TouchAction PlayEvent 60367 true true TouchAction PlayEvent 520702 false false
to play another event instead. - Changed existing tile properties:
layer property reason Back NoSpawn Added NoSpawn false form, which disables any previous NoSpawn property on the tile. For example, this can be used to enable spawning on a tile which has a NoSpawn tile index property. TouchAction Bus Removed. This wasn't used by the game or mods. TouchAction Emote Fixed error if the specified NPC isn't found. Treasure Added Treasure Item <item ID>
form which accepts a qualified or unqualified item ID.Buildings Action ItemChest
Action Minecart
Action RemoveChestRemoved. These weren't used by the game or mods. Action Kitchen Now works in any location (including those without a fridge).
Other location/map changes
- Farm data:
- Added SpawnMonstersByDefault field to Data/AdditionalFarms to set the default value of the 'spawn monsters at night' advanced save option.
- Fixed crash on new-save screen if the farm type's tooltip has no description.
- General location data:
- All locations can now have animals. The IAnimalLocation is now obsolete and implemented by GameLocation.
- Added new fishing areas to simplify compatibility between fish & map mods (specifically for hilltop farm, wilderness farm, town, and desert).
- Added a descriptive error when a required location or layer isn't found. Mods can use map.RequireLayer and Game1.RequireLocation to get a location with similar error-checking.
- Added WarpPathfindingCache for C# mods, which modularizes the NPC warp route logic. You can edit its IgnoreLocationNames, OverrideTargetNames, and GenderRestrictions fields if needed for custom locations.
- Game logic which checks tile indexes is now more fault-tolerant, so it won't crash if an expected tile was edited.
- Finished migrating DecoratableLocation flooring/wallpaper areas to string IDs (started in Stardew Valley 1.5.5).
- General map changes:
- Added validation for map properties and tile properties. If the format is invalid, the game will now log a detailed error and skip it.
- Removed unused path tiles in Maps/paths and all map files.
- Location context data:
- Building interiors now inherit their parent's location context by default.
- Added Game1.locationContextData to cache the data from Data/LocationContexts.
- Added constants for the vanilla context IDs like LocationContexts.IslandId.
- Added validation for required location context IDs (and LocationContexts.Require(id) for mod logic).
- Removed the Name field in Data/LocationContexts, which duplicated the ID.
- Added methods to simplify common operations:
type method effect Building GetParentLocation Get the location which contains this building. IsInCurrentLocation Get whether the building is in the same location as the current player. HasIndoors Get whether the building has an interior location. GetIndoors Get the location within this building, if applicable. HasIndoorsName Get whether the building has an interior location and its unique name matches the given value (like building.HasIndoorsName("FarmHouse")
).GetIndoorsName Get the unique name of the location within this building, if applicable. ... see also other building changes for non-location methods. Cabin
FarmHouseGetCellar Get the cellar location linked to this cabin, if any. CanAssignFarmhand
AssignFarmhand(Cabin only) Check whether the cabin is available to assign to a farmhand, or perform the assignment. HasOwner Get whether the home has an assigned player, regardless of whether they've finished creating their character. OwnerId Get the unique ID of the player who owns this home, if any. IsOwnedByCurrentPlayer Get whether the cabin belongs to the current player. IsOwnerActivated Get whether the home has an assigned player and they've finished creating their character. HasNpcSpouse Get whether the player who owns this home is married to any NPC (when used like HasNpcSpouse()) or a specific NPC (like HasNpcSpouse(name)). This also replaces shouldShowSpouseRoom(). Farm GetStarterFarmhouseLocation Get the default tile position for the farmhouse. (See also farm.GetMainFarmHouseEntry().) GetStarterPetBowlLocation Get the default tile position for the pet bowl. GameLocation AddDefaultBuildings Can be overridden to add custom buildings when the location is created and/or loaded. These can either be re-added whenever they're missing (like the vanilla farmhouse), or only built once on save creation (like the vanilla pre-built cabins). This replaces the former farm.AddModularShippingBin() method.
GetFridge
GetFridgePositionGet the fridge's chest or tile position, if the location has one. GetSeason
GetSeasonIndex
GetSeasonKeyGet the local season that applies within the location as an enum, number (like 0 for spring), or string (like spring) respectively. For example, it's always summer on Ginger Island. GetWeather
IsDebrisWeatherHere
IsLightningHere
IsRainingHere
IsSnowingHereGet the current weather in this location's context, regardless of whether the player is indoors and sheltered from it. InDesertContext
InIslandContext
InValleyContextGet whether this location is within the Island or Default location context respectively. IsActiveLocation Get whether this location is actively synced to the current player (see farmhand shadow world). IsTemporary Get whether this is a temporary location for a festival or minigame. This is cached based on the location name (e.g. locations starting with Temp or some other specific names). GetLocationContextId Get the ID of the location context in Data/LocationContexts which contains this building. GetContainingBuilding Get the building instance which contains this location (like the cabin for a cabin interior), if applicable. GetParentLocation Get the parent location which contains this one (like the farm for a cabin interior), or null if it has no parent. GetRootLocation Get the parent location which contains this one (like the farm for a cabin interior), or the location itself if it has no parent. GetInstancedBuildingInteriors Get all building interiors within this location which are instanced to the building (i.e. not in Game1.locations separately). GetMapPropertySplitBySpaces
GetTilePropertySplitBySpacesGet the value of a map/tile property and split it into individual words. If the map/tile property isn't defined, returns an empty array. For example:
string[] fields = Game1.currentLocation.GetMapPropertySplitBySpaces("ScreenshotRegion");
HasMapPropertyWithValue Get whether a map property is defined and has a non-empty value. For example:
bool canUseCasks = Game1.currentLocation.HasMapPropertyWithValue("CanCaskHere");
StoreHayInAnySilo Add hay to any silo with free space (preferring silos in the current location, then the farm, then anywhere). TryGetMapProperty Get a map property value as a string, if it's defined. For example:
if (this.TryGetMapProperty("Warps", out string warps)) { // ... }
TryGetMapPropertyAs Get a map property and parse it into into a Point, Rectangle, or Vector2 value. For example:
if (!this.TryGetMapPropertyAs("MailboxLocation", out Point position)) { position = new Point(68, 16); // default value }
removeObjectsAndSpawned Remove all objects, bushes, resource clumps, and terrain features within a tile area. OnBuildingConstructed
OnBuildingMoved
OnBuildingDemolishedThese methods are called for all players when any player constructs, moves, or demolishes a building. LibraryMuseum HasDonatedArtifacts() Get whether any items have been donated to the museum. HasDonatedArtifactAt(tile) Get whether any donated item is currently placed at the given tile position within the museum. HasDonatedArtifact(itemId) Get whether an artifact with the given qualified or unqualified item ID has been donated to the museum. MineShaft GetLevelName Get the location name for a generated mine or Skull Cavern level. For example:
string locationName = MineShaft.GetLevelName(10); // returns "UndergroundMine10" Game1.warpFarmer(locationName, 0, 0, false);
IsGeneratedLevel Get whether a location or location name is a generated mine or Skull Cavern level. For example:
string locationName = "UndergroundMine10"; bool isMine = MineShaft.IsGeneratedLevel(locationName, out int level); // returns true, 10
VolcanoDungeon GetLevelName
IsGeneratedLevelEquivalent to the matching MineShaft methods, but for the Volcano Dungeon.
- Added map/tile property TryAdd/TryGetValue extensions in StardewValley.Extensions for string property values. For example, this lets you do map.Properties.TryGetValue(key, out string value).
- MineShaft.tryToAddMonster now returns whether a monster was added.
- Game1.GetNumberBuildingsConstructed and location.getNumberBuildingsConstructed now have overloads to count all building types and/or specify whether to count under-construction buildings.
- Fixed location.refurbishMapPortion copying Back source properties to the Building target layer.
- Fixed door warps in custom indoor locations not consistently detected by the game.
What's new for buildings
Custom buildings
You can now add custom buildings by editing the Data/Buildings asset. This consists of a string → model lookup, where...
- The key is a unique building ID. The ID should only contain alphanumeric/underscore/dot characters, and should ideally be prefixed with your mod ID like Example.ModId_BuildingName.
- The value is a model with the fields listed below.
Required fields
field effect Name
DescriptionA tokenizable string for the display name and description (e.g. shown in the construction menu). Texture The asset name for the texture under the game's Content folder. Construction
field effect Builder (Optional) The NPC from whom you can request construction. The vanilla values are Robin and Wizard, but you can specify a different name if a C# mod opens a construction menu for them. Defaults to Robin. If omitted, it won't appear in any menu. BuildCost (Optional) The gold cost to construct the building. Defaults to 0g.
BuildMaterials (Optional) The materials you must provide to start construction, as a list of models with these fields: field effect Id (Optional) A key which uniquely identifies this entry within the current list. The ID should only contain alphanumeric/underscore/dot characters. Defaults to the ItemId if not specified. ItemId The required item ID (qualified or unqualified). Amount The number of the item required. BuildDays (Optional) The number of days needed to complete construction (e.g. 1 for a building completed the next day). If set to 0, construction finishes instantly. Defaults to 0. BuildCondition (Optional) A game state query which indicates whether the building should be available in the construction menu. Defaults to always available. BuildMenuDrawOffset (Optional) A pixel offset to apply to the building sprite when drawn in the construction menu. Default none. AdditionalPlacementTiles (Optional) The extra tiles to treat as part of the building when placing it through the construction menu. For example, the farmhouse uses this to make sure the stairs are clear. This consists of a list of models with these fields: field effect TileArea The tile area relative to the top-left corner of the building, specified as an object with X, Y, Width, and Height fields. OnlyNeedsToBePassable (Optional) Whether this area allows tiles that would normally not be buildable, so long as they are passable. For example, this is used to ensure that an entrance is accessible. Default false. IndoorItems (Optional) The items to place in the building interior when it's constructed or upgraded. This consists of a list of models with these fields: field effect Id A key which uniquely identifies this entry within the current list. The ID should only contain alphanumeric/underscore/dot characters. For custom entries, this should be prefixed with your mod ID like Example.ModId_EntryId. ItemId The qualified item ID for the item to place. Tile The tile position at which to place the item, specified as an object with X and Y fields. Indestructible (Optional) Whether to prevent the player from destroying, picking up, or moving the item. Default false. MagicalConstruction (Optional) Whether the building is magical. This changes the carpenter menu to a mystic theme while this building's blueprint is selected, and completes the construction instantly when placed. AddMailOnBuild (Optional) A list of letter IDs to send to all players when the building is constructed for the first time. Upgrades
field effect BuildingToUpgrade (Optional) The ID of the building for which this is an upgrade, or omit to allow constructing it as a new building. For example, the Big Coop sets this to "Coop". Any numbers of buildings can be an upgrade for the same building, in which case the player can choose one upgrade path. IndoorItemMoves (Optional) When applied as an upgrade to an existing building, the placed items in its interior to move when transitioning to the new map. This is a list of models with these fields: field effect Id A key which uniquely identifies this entry within the current list. The ID should only contain alphanumeric/underscore/dot characters. For custom entries, this should be prefixed with your mod ID like Example.ModId_EntryId. Source The tile position on which any item will be moved. Destination The tile position to which to move the item. Size (Optional) The tile size of the area to move, specified as a model with X and Y fields. Defaults to a 1×1 area. If this is multiple tiles, the Source and Destination specify the top-left coordinate of the area. UpgradeSignTile (Optional) The tile position relative to the top-left corner of the building where the upgrade sign will be placed when Robin is building an upgrade, in the form " <x>
,<y>
". Defaults to approximately "5, 1" if the building interior type is Shed, else "0, 0".UpgradeSignHeight (Optional) The pixel height of the upgrade sign when Robin is building an upgrade. Defaults to 0. Exterior behavior
field effect Size (Optional) The building's width and height when constructed, measured in tiles. Defaults to a 1 x 1 area. CollisionMap (Optional) An ASCII text block which indicates which of the building's tiles the players can walk onto, where each character can be X (blocked) or O (passable). Defaults to all tiles blocked. For example, a stable covers a 2x4 tile area with the front two tiles passable:
XXXX XOOX
When the collision map is parsed, leading/trailing whitespace is trimmed (both for the entire map and for each line). In JSON, you can specify it in two forms:
// single line with \n line breaks "CollisionMap": "XXXX\nXOOX" // multi-line with optional indentation "CollisionMap": " XXXX XOOX "
HumanDoor (Optional) The position of the door that can be clicked to warp into the building interior. This is measured in tiles relative to the top-left corner tile. Defaults to disabled. AnimalDoor (Optional) The position and size of the door that animals use to enter/exit the building, if the building interior is an animal location, specified as an object with X, Y, Width, and Height fields. This is measured in tiles relative to the top-left corner tile. Defaults to disabled. AnimalDoorOpenDuration
AnimalDoorCloseDuration(Optional) The duration of the open/close animation for the animal door, measured in milliseconds. If omitted, the door switches to the open/closed state instantly. AnimalDoorOpenSound
AnimalDoorCloseSound(Optional) The sound which is played once each time the animal door is opened/closed. Disabled by default. Exterior appearance
field effect SourceRect (Optional) The building's pixel area within the Texture, specified as an object with X, Y, Width, and Height fields. Defaults to the entire texture. Skins (Optional) The appearances which can be selected from Robin's menu (like stone/plank/log cabins), in addition to the default appearance based on Texture. This consists of a list of models with these fields: field effect Id A key which uniquely identifies the skin. The ID should only contain alphanumeric/underscore/dot characters. For custom skins, it should be prefixed with your mod ID like Example.ModId_SkinName. Name
DescriptionTokenizable strings for the skin's display name and description. Texture The asset name for the texture under the game's Content folder. Condition (Optional) A game state query which indicates whether this skin should be available to apply. This doesn't change buildings which already have it applied. Defaults to always true. BuildDays
BuildCost
BuildMaterials(Optional) If set, overrides the equivalent field in the building data. ShowAsSeparateConstructionEntry (Optional) Whether this skin should be shown as a separate building option in the construction menu (like cabins). Default false. Metadata (Optional) Equivalent to the Metadata field on the building. Properties defined in this field are added to the building's metadata when this skin is active, overwriting the previous property with the same name if applicable. Default none. FadeWhenBehind (Optional) Whether the building should become semi-transparent when the player is behind it. Default true. DrawOffset (Optional) A pixel offset applied to the building sprite's placement in the world. Default 0. SeasonOffset (Optional) A pixel offset to apply each season. This is applied to the SourceRect position by multiplying the offset by 0 (spring), 1 (summer), 2 (fall), or 3 (winter). Default 0, so all seasons use the same source rect. SortTileOffset (Optional) A Y tile offset applied when figuring out render layering. For example, a value of 2.5 will treat the building as if it was 2.5 tiles further up the screen for the purposes of layering. Default 0. DrawLayers (Optional) A list of textures to draw over or behind the building, with support for conditions and animations. This consists of a list of models with these fields: field effect Id A key which uniquely identifies this entry within the current list. The ID should only contain alphanumeric/underscore/dot characters. For custom entries, this should be prefixed with your mod ID like Example.ModId_DrawLayerId. SourceRect The pixel area within the texture to draw, formatted like " <x>
<y>
<width>
<height>
". If the overlay is animated via FrameCount, this is the area of the first frame.DrawPosition The tile position at which to draw the top-left corner of the texture, relative to the building's top-left corner tile. Texture (Optional) The asset name of the texture to draw. Defaults to the building's default Texture field. DrawInBackground (Optional) Whether to draw the texture behind the building sprite (i.e. underlay) instead of over it. SortTileOffset (Optional) A Y tile offset applied when figuring out render layering. For example, a value of 2.5 will treat the texture as if it was 2.5 tiles further up the screen for the purposes of layering. Default 0. OnlyDrawIfChestHasContents (Optional) The ID of a chest defined in the Chests field which must contain items. If it's empty, this overlay won't be rendered. Default none. FrameCount
FramesPerRow
FrameDuration(Optional) If FrameCount is more than one, the building overlay will be animated automatically. For each frame, the SourceRect will be offset by its Width to the right up to FramesPerRow - 1 times, and then down by its Height. Each frame will be rendered on-screen for FrameDuration milliseconds before switching to the next frame. For example, if you set FrameCount to 6 and FramesPerRow to 3, the building will expect the frames to be laid out like this in the spritesheet (where frame 1 matches SourceRect):
┌───┬───┬───┐ │ 1 │ 2 │ 3 │ ├───┼───┼───┤ │ 4 │ 5 │ 6 │ └───┴───┴───┘
AnimalDoorOffset (Optional) A pixel offset applied to the draw layer when the animal door is open. While the door is opening, the percentage open is applied to the offset (e.g. 50% open = 50% offset). DrawShadow (Optional) Whether to draw an automatic shadow along the bottom edge of the building's sprite. Default true. Interior
field effect IndoorMap (Optional) The name of the map asset under Maps to load for the building interior. For example, "Shed" will load the shed's Maps/Shed map. IndoorMapType (Optional) The full name of the C# location class which will manage the building's interior location. This must be one of the vanilla types to avoid a crash when saving. There are too many to list here, but the most useful types are likely... - StardewValley.AnimalHouse;
- StardewValley.Locations.Cabin;
- StardewValley.Locations.Cellar;
- StardewValley.Locations.DecoratableLocation;
- StardewValley.Locations.FarmCave;
- StardewValley.Locations.FarmHouse;
- StardewValley.Shed;
- and StardewValley.SlimeHutch.
Defaults to the generic StardewValley.GameLocation class.
NonInstancedIndoorLocation (Optional) The name of the existing global location to treat as the building's interior, like FarmHouse and Greenhouse for their buildings. Each location can only be used by one building. If the location is already in use (e.g. because the player has two of this building), each subsequent building will use the IndoorMap and IndoorMapType instead. For example, the first greenhouse will use the global Greenhouse location, and any subsequent greenhouse will use a separate instanced location.
MaxOccupants (Optional) The maximum number of animals who can live in this building. AllowAnimalPregnancy (Optional) Whether animals can get pregnant and produce offspring in this building. Default false. ValidOccupantTypes (Optional) A list of building IDs whose animals to allow in this building too. For example, [ "Barn", "Coop" ]
will allow barn and coop animals in this building. Default none.Item processing
field effect HayCapacity (Optional) The amount of hay that can be stored in this building. If built on the farm, this works just like silos and contributes to the farm's available hay. ItemConversions (Optional) The item processing rules which take input items and convert them into output items using the inventories defined by Chests. This consists of a list of models with these fields: field effect Id A key which uniquely identifies this rule within the current list. The ID should only contain alphanumeric/underscore/dot characters. For custom entries, this should be prefixed with your mod ID like Example.ModId_RuleId. RequiredTags A list of context tags to match against an input item. An item must have all of these tags to be accepted. SourceChest The ID of the inventory defined in Chests from which to take input items. DestinationChest The ID of the inventory defined in Chests in which to store output items. ProducedItems The output items produced when an input item is converted. This consists of a list of models with these fields: field effect common fields See item spawn fields for the generic item fields supported by machine output. If set to an item query which returns multiple items, one of them will be selected at random.
Chance (Optional) The probability that the item will be produced, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance). RequiredCount (Optional) The number of the input item to consume. Default 1. MaxDailyConversions (Optional) The maximum number of the input item which can be processed each day. Each conversion rule has its own separate maximum (e.g. if you have two rules each with a max of 1, then you can convert one of each daily). Set to -1 to allow unlimited conversions. Default 1. Chests (Optional) The input/output inventories that can be accessed from a tile on the building exterior. The allowed items are defined by the separate ItemConversions field. This is a list of models with these fields: field effect Id A key which uniquely identifies this chest within the current list. The ID should only contain alphanumeric/underscore/dot characters. For custom entries, this should be prefixed with your mod ID like Example.ModId_ActionId. This is referenced from the ItemConversions field.
Type The inventory type. This must be one of: - Chest: show a normal chest UI on click.
- Collect: provides items for the player to collect. Clicking the tile will do nothing (if empty), grab the item directly (if it only contains one item), else show a grab-only inventory UI.
- Load: lets the player add items for the building to process.
Sound (Optional) The sound to play once when the player clicks the chest. InvalidItemMessage
InvalidCountMessage
ChestFullMessage(Optional) A tokenizable string to show when the player tries to add an item to the chest when... - it isn't a supported item;
- it's supported but they don't have enough in their inventory;
- the chest has no more room to accept it.
If omitted, the player interaction is ignored with no message shown.
InvalidItemMessageCondition (Optional) A game state query which indicates whether InvalidItemMessage should be shown. This can use item-related queries like ITEM_TYPE. Defaults to always true. DisplayTile (Optional) The chest's position on the building exterior, measured in tiles from the top-left corner of the building, specified in the form " <x>
,<y>
". This affects the position of the 'item ready to collect' bubble. If omitted, the bubble is disabled.DisplayHeight (Optional) If DisplayTile is set, the chest's tile height like 1.5. Tile interactions
field effect ActionTiles (Optional) A list of tiles which the player can click to trigger an Action map tile property. This consists of a list of models with these fields: field effect Id A key which uniquely identifies this entry within the current list. The ID should only contain alphanumeric/underscore/dot characters. For custom entries, this should be prefixed with your mod ID like Example.ModId_ActionId. Tile The tile position, relative to the building's top-left corner tile. Action The tokenizable string for the action to perform, excluding the Action prefix. For example, "Dialogue Hi there @!" to show a messagebox like "Hi there <player name>!". The tokenizable string is expected before the action is raised. See the list of tile properties for useful Action values. DefaultAction (Optional) The default tile action if the clicked tile isn't in ActionTiles. Default none. TileProperties (Optional) The map tile properties to set. This consists of a list of models with these fields: field effect Id A key which uniquely identifies this entry within the current list. The ID should only contain alphanumeric/underscore/dot characters. For custom entries, this should be prefixed with your mod ID like Example.ModId_EntryId. Name The tile property name to set. Value (Optional) The tile property value to set, or omit to set a null value. Layer The name of the map layer whose tiles to change. TileArea The tiles to which to add the property, relative to the top-left corner of the building's collision box. This is specified as an object with X, Y, Width, and Height fields. AdditionalTilePropertyRadius (Optional) When checking whether the player clicked on a TileProperties tile, an added distance around the building at which tile locations may be placed. Default 0, so only tile properties within the normal building bounds will work. Advanced
field effect Metadata (Optional) A list of custom properties applied to the building, which can optionally be overridden per-skin in the Skins field. Default none. The base game recognizes these properties:
property description ChimneyPosition: <x>
<y>
(Optional) The pixel position at which to place a chimney on the building exterior, relative to the top-left corner of the sprite. This will apply the same logic as the farmhouse chimney (e.g. producing smoke if there's a lit fireplace inside the building). ChimneyPosition [upgrade level]
:<x>
<y>
(Optional, for farmhouses/cabins only) Override ChimneyPosition for the given upgrade level, starting from 0 for the initial farmhouse/cabin. If there's no override for the current upgrade level, the highest override for a lower upgrade level is used (if any). For example, ChimneyPosition3 would be used for the third house upgrade (and the fourth if there's no ChimneyPosition4). This can also contain arbitrary custom properties, which C# mods can read using building.GetMetadata(key).
BuildingType (Optional) The full name of the C# type to instantiate for the building instance. Defaults to a generic Building instance. ⚠ Caution: this is meant to support vanilla building types like StardewValley.Shed. Setting this to a non-vanilla type will cause a crash when it's written to the save file, and may cause crashes in multiplayer. If you need custom behavior, consider handling it in C# based on the building type instead of creating a custom subclass; otherwise you'll need a framework mod like SpaceCore to handle serialization and multiplayer sync.
ModData (Optional) A string → string lookup of arbitrary modData values to attach to the building when it's constructed. CustomFields The custom fields for this entry. Build anywhere
Buildings and animals are no longer hardcoded to the farm location (except cabins and the farmhouse which still are). You can allow building construction for any location using the new CanBuildHere and related map properties. The game will adjust accordingly (e.g. Robin will let you choose where to construct the building).
Other building changes
- See also: other location changes for location-related building changes.
- General building changes
- Building display names & descriptions are now in Strings/Buildings for reuse.
- Removed Data/Blueprints. This has been replaced by Data/Buildings (building data) and Strings/Buildings (display names & descriptions).
- Added methods to simplify common operations:
type method effect Building CreateInstanceFromId Create a building instance from its type ID in Data/Buildings. For example: Building shippingBin = Building.CreateInstanceFromId("Shipping Bin", Vector2.Zero); // creates an instance of StardewValley.Buildings.ShippingBin
GetData
TryGetDataGet the data for the building's type from Data/Building. GetMetadata Get a value from the Metadata field in Data/Buildings for this building. GetPaintDataKey Get the key in Data/PaintData for this building, if it has any. ReloadBuildingData Apply the latest data in Data/Buildings to this building. FinishConstruction If the building is being constructed or upgrade, instantly finish doing so. UpdateTransparency Update the building transparency on tick for the local player's position. This method mainly exists to let mods override/patch the transparency logic.
Farm GetMainFarmHouse Get the main farmhouse building. GameLocation OnParentBuildingUpgraded Called when the building containing this location is upgraded, if applicable.
- Added building id field, which uniquely identifies each building in the world.
- Junimo hut changes
- The JunimoHut.cropHarvestRange field is now per-building and editable.
- Fish pond changes
- In Data/FishPondData, added a Precedence field which sets the order in which entries are checked for a match (with lower values checked first). This ensures that the fallback entries are checked after specific fish. For consistency, vanilla entries use these values:
precedence used for 0
(default value)specific fish 100 custom groups (e.g. desert fish) 500 broad fish type (e.g. ocean fish) 1000 fallback (e.g. fish category) - Legendary fish can now be added to fish ponds if they have an entry in Data/FishPondData.
What's new for NPCs
Custom NPCs
Custom NPC data has been overhauled in 1.6. The new Data/Characters asset (which replaces Data/NPCDispositions + Data/spousePatios + Data/spouseRooms) uses a data model format that's easier to edit and understand, and has a lot of fields to customize previously-hardcoded data.
Format
This consists of a string → model lookup, where...
- The key is the unique internal NPC name.
- The value is a model with the following fields.
- Basic info:
-
field effect DisplayName A tokenizable string for the NPC's display name. Language (Optional) The language spoken by the NPC. One of Default (the default language understood by the player) or Dwarvish (which the player can only understand after finding the Dwarvish translation guide). Default Default. Gender (Optional) The NPC's gender identity. One of Female, Male, or Undefined. Default Undefined. Age (Optional) The general age of the NPC. One of Child, Teen, or Adult. Default Adult. This affects generated dialogue lines (e.g. a child might say "stupid" and an adult might say "depressing"), generic dialogue (e.g. a child might respond to dumpster diving with "Eww... What are you doing?" and a teen would say "Um... Why are you digging in the trash?"), and the gift they choose as Feast of the Winter Star gift-giver. Children are also excluded from item delivery quests.
Manner (Optional) A measure of the character's general politeness, which affects some generic dialogue lines. One of Neutral, Polite, or Rude. Default Neutral. SocialAnxiety (Optional) A measure of the character's comfort with social situations, which affects some generic dialogue lines. One of Neutral, Outgoing, or Shy. Default Neutral. Optimism (Optional) A measure of the character's overall optimism. One of Neutral, Negative, or Positive. Default Neutral. BirthSeason (Optional if non-social) The season name (case-sensitive) for the NPC's birthday. One of spring, summer, fall, or winter. Default none. BirthDay (Optional if non-social) The day number for the NPC's birthday. Default 0. HomeRegion (Optional) The region of the world in which the NPC lives (one of Desert, Town, or Other). For example, only Town NPCs are counted for the introductions quest, can be selected as a secret santa for the Feast of the Winter Star, or get a friendship boost from the Luau. Default Other. - Social features:
-
field effect CanBeRomanced (Optional) Whether the NPC can be dated and romanced. This enables romance features for this NPC (like a 'single' label in the social menu, bouquet gifting, and marriage). Default false. LoveInterest (Optional) Unused. Calendar (Optional) Determines when the NPC's birthday is shown in the calendar. Possible values: value effect HiddenAlways They never appear in the calendar. HiddenUntilMet Until the player meets them, they don't appear in the calendar. AlwaysShown They always appear in the calendar. Defaults to AlwaysShown.
SocialTab (Optional) Determines how the NPC is shown on the social tab when unlocked. Possible values: value effect HiddenAlways They never appear in the social tab. HiddenUntilMet Until the player meets them, they don't appear on the social tab. UnknownUntilMet Until the player meets them, their name on the social tab is replaced with "???". AlwaysShown They always appear in the social tab (including their name). Defaults to UnknownUntilMet.
SocialTabIconSourceRect (Optional) The pixel area in the character's sprite texture to show as their icon in the social menu. This should be approximately 24x24 pixels or smaller. Defaults to part of their first sprite. SpouseRoom (Optional) The NPC's spouse room in the farmhouse when the player marries them, if applicable. If this is omitted for a marriageable NPC, they'll use Abigail's spouse room by default. This consists of a model with these fields:
field effect MapAsset (Optional) The asset name for the spouse room map. The Map/ prefix is added automatically and shouldn't be included. Defaults to spouseRooms. MapSourceRect (Optional) The tile area within the MapAsset containing the spouse's room. This should usually be a 6x9 tile area, though the game will try to adjust to a different size. Specified as a model with X, Y, Width, and Height fields. Defaults to (0, 0, 6, 9). SpousePatio (Optional) The NPC's patio area on the farm when the player marries them, if any. Default none. This consists of a model with these fields:
field effect MapAsset (Optional) The asset name for the patio area. The Map/ prefix is added automatically and shouldn't be included. Defaults to spousePatios. MapSourceRect (Optional) The tile area within the MapAsset containing the spouse's patio area. This must be a 4x4 tile area. Specified as a model with X, Y, Width, and Height fields. Defaults to (0, 0, 4, 4). SpriteAnimationFrames (Optional) The spouse's animation frames when they're in the patio. Each frame is an array containing [0] the sprite index in their spritesheet, and [1] the optional duration in milliseconds (default 100). If omitted or empty, the NPC won't be animated. For example, here is Abigail playing the flute:
"SpriteAnimationFrames": [ [16, 500], // show index 16 for 500ms [17, 500], [18, 500], [19] // if duration is omitted, defaults to 100ms ]
SpriteAnimationPixelOffset (Optional) The pixel offset to apply to the NPC's sprite when they're animated in the patio, specified as a model with X and Y fields. This is ignored if the NPC isn't animated via SpriteAnimationFrames. Default none. SocializeConditions (Optional) A game state query which indicates whether to enable social features (like birthdays, gift giving, friendship, and an entry in the social tab). Default true. CanVisitIslandCondition (Optional) A game state query which indicates whether the NPC can visit the Ginger Island resort once it's unlocked. The NPC must be social (per SocializeConditions) to visit the island, regardless of this value. Default true. ExcludeFromIntroductionsQuest (Optional) Whether this NPC will be ignored for the introductions quest. Default false. ExcludeFromPerfectionScore (Optional) Whether to exclude this NPC when checking whether the player has max friendships with every NPC for the perfection score. Default false. EndSlideShow (Optional) How the NPC appears in the end-game perfection slide show. Possible values: value effect Hidden The NPC doesn't appear in the slide show. MainGroup The NPC is added to the main group of NPCs which walk across the screen. TrailingGroup The NPC is added to the trailing group of NPCs which follow the main group. Defaults to MainGroup.
FriendsAndFamily (Optional) The NPC's closest friends and family, as a dictionary where the key is the other NPC's internal name and the value is an optional tokenizable string for the name to use in dialogue text (like 'mom'). Default none. This affects generic dialogue for revealing likes and dislikes to family members, and may affect inlaw_<NPC> dialogues. This isn't necessarily comprehensive.
- Spawn rules:
-
field effect UnlockConditions (Optional) A game state query which indicates whether the NPC should be added to the world, checked when loading a save and when ending each day. This only affects whether the NPC is added when missing; returning false won't remove an NPC that's already been added. Defaults to true. SpawnIfMissing (Optional) Whether to add this NPC to the world if they're missing (if the UnlockConditions match and HomeLocation is valid). Default true. Home (Optional) The default place where this NPC spawns and returns each day. If there are multiple entries, the first matching one is used. This consists of a list of models with these fields:
field effect ID A key which uniquely identifies this entry. The ID should only contain alphanumeric/underscore/dot characters. When adding a custom home to an existing NPC, this should be prefixed with your mod ID like Example.ModId_HomeName; when adding a single home for your own NPC, you can just set the ID to Default. Location (Optional) The internal name for the home location where this NPC spawns and returns each day. Default none. Tile (Optional) The tile position within the home location where this NPC spawns and returns each day. Specified as a model with X and Y fields. Defaults to (0, 0). Direction (Optional) The default direction the NPC faces when they start each day. The possible values are down, left, right, and up. Defaults to up. Condition (Optional) A game state query which indicates whether this entry can be selected. Default true. - Appearance & sprite:
-
field effect TextureName (Optional) The last segment of the NPC's portrait and sprite asset names. For example, set to Abigail to use Portraits/Abigail and Characters/Abigail respectively. Defaults to the internal NPC name. Appearance (Optional) The portrait/sprite textures to use. This can list any number of appearance options. They'll be sorted by Precedence value (with lower values taking priority), then filtered to those whose fields match. If multiple matching appearances have precedence, one entry is randomly chosen based on their relative weight. This randomization is stable per day, so the NPC always makes the same choice until the next day. If a portrait/sprite can't be loaded (or no appearances match), the NPC will use the default asset based on TextureName.
The NPC rechecks this field each time they change location.
This consists of a list of models with these fields:
field effect Id A key which uniquely identifies this entry. The ID should only contain alphanumeric/underscore/dot characters. When adding a custom appearance to an existing NPC, this should be prefixed with your mod ID like Example.ModId_AppearanceName. Condition (Optional) A game state query which indicates whether this entry can be selected. Default true. Portrait
Sprite(Optional) The asset name for the portraits and/or sprites texture to load. If omitted or it can't be loaded, it will default to the default asset per the Texture field. IsIslandAttire (Optional) Whether this is island beach attire worn at the resort. Default false. This is mutually exclusive: NPCs will never wear it in other contexts if it's true, and will never wear it as island attire if it's false.
Precedence (Optional) The order in which this entry should be checked, where lower values are checked first. This can be a negative value. Default 0. Weight (Optional) If multiple entries with the same Precedence match, the relative weight to use when randomly choosing one. Default 1. For example, let's say two appearance entries match: one has a weight of 2, and the other has a weight of 1. Their probability of being chosen is 2/3 and 1/3 respectively.
Note: the default textures based on TextureName must still exist, even if you use this field to override them.
Size (Optional) The pixel size of the individual sprites in their overworld sprite spritesheet. Specified as a model with X and Y fields. Defaults to (16, 32). Note: sizes bigger than 16×32 will cause issues like broken spawning, pathfinding, misalignment in the perfection end-game slide show, etc.
Breather (Optional) Whether the chest on the NPC's overworld sprite puffs in and out as they breathe. Default true. KissSpriteIndex (Optional) If the NPC can be married, the sprite index within their Texture to use when kissing a player. Default 28. KissSpriteFacingDirection (Optional) Whether the character is facing right (true) or left (false) in their KissSpriteIndex. The sprite will be flipped as needed to face the player. Default true. - Hidden gift log emote:
-
field effect HiddenProfileEmoteSound (Optional) For the hidden gift log emote, the cue ID for the sound played when clicking the sprite. Defaults to drumkit6. HiddenProfileEmoteDuration (Optional) For the hidden gift log emote, how long the animation plays measured in milliseconds. Defaults to 4000 (4 seconds). HiddenProfileEmoteStartFrame (Optional) For the hidden gift log emote, the index within the NPC's overworld sprite spritesheet at which the animation starts. If omitted for a vanilla NPC, the game plays a default animation specific to that NPC; if omitted for a custom NPC, the game just shows them walking while facing down. HiddenProfileEmoteFrameCount (Optional) For the hidden gift log emote, the number of frames in the animation. The first frame corresponds to HiddenProfileEmoteStartFrame, and each subsequent frame will use the next sprite in the spritesheet. Default 1. This has no effect if HiddenProfileEmoteStartFrame isn't set.
HiddenProfileEmoteFrameDuration (Optional) For the hidden gift log emote, how long each animation frame is shown on-screen before switching to the next one, measured in milliseconds. Default 200. This has no effect if HiddenProfileEmoteStartFrame isn't set.
- Advanced:
-
field effect FestivalVanillaActorIndex (Optional, Specialized) The NPC's index in the Maps/characterSheet tilesheet, if applicable. This is used for placing vanilla NPCs in festivals from the map; custom NPCs should use the <layer>_additionalCharacters field in the festival data instead. CustomFields The custom fields for this entry.
Examples
For example, this content pack adds a new Amabel NPC with full social features:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/Characters", "Entries": { "Example.ModId_Amabel": { "DisplayName": "Amabel", // this would normally use {{i18n:}} to support translations "BirthSeason": "Fall", "BirthDay": 14, "HomeRegion": "Town", "Gender": "Female", "Age": "Teen", "Manner": "Rude", "SocialAnxiety": "Outgoing", "Optimism": "Neutral", "CanBeRomanced": true, "LoveInterest": "Abigail", "Home": [ { "Id": "Default", "Location": "SeedShop", "Tile": { "X": 1, "Y": 9 }, "Direction": "Left" } ] } } } ] }
You can also add non-social NPCs which don't have birthdays or friendship points, accept gifts, give quests, etc:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/Characters", "Entries": { "Example.ModId_Belwick": { "DisplayName": "Belwick", // this would normally use {{i18n:}} to support translations "SocialTab": "HiddenAlways", "SocializeConditions": "FALSE", "ExcludeFromIntroductionsQuest": true, "ExcludeFromPerfectionScore": true, "EndSlideShow": true } } } ] }
Custom NPC appearance
Each NPC can now have any number of custom portraits/sprites in Data/Characters with arbitrary conditions. This lets mods add features like indoor/outdoor outfits without the performance impact of reloading textures. If multiple outfits apply, the game will choose between them with a day-stable randomization.
See the Appearance field in custom NPC data for more info.
Custom farm animals
You can now create and customize farm animals by editing the revamped Data/FarmAnimals asset.
This consists of a string → model lookup, where...
- The key is a unique farm animal ID. This should only contain alphanumeric/underscore/dot characters, and custom entries should be prefixed with your mod ID like Example.ModId_AnimalId.
- The value is a model with the fields listed below.
Main info
field effect DisplayName A tokenizable string for the animal type's display name. House The building ID for the main building type that houses this animal. The animal will also be placeable in buildings whose ValidOccupantTypes field contains this value. Gender (Optional) The possible genders for the animal type. Currently this only affects the text shown after purchasing the animal, like "Great! I'll send little <name> to [his/her] new home right away". Default Female. The possible values are:
value effect Male
FemaleFarm animals of this type are always male or always female. MaleOrFemale The gender of each animal is randomized based on its internal unique ID. Animal shop
These fields affect how this farm animal type is shown in Marnie's animal shop. Animals are automatically listed if they have a valid PurchasePrice value.
field effect PurchasePrice (Optional if not purchaseable) Half the cost to purchase the animal (the actual price is double this value), or a negative value to disable purchasing this animal type. Default -1. ShopTexture (Optional if not purchaseable) The asset name for the icon texture to show in shops. Defaults to LooseSprites/Cursors or LooseSprites/Cursors2 based on the animal's position within the loaded data (but using the default isn't recommended if it's purchaseable). ShopSourceRect (Optional if not purchaseable) The pixel area within the ShopTexture to draw, specified as an object with X, Y, Width, and Height fields. This should be 32 pixels wide and 16 high. Ignored if ShopTexture isn't set. RequiredBuilding (Optional) The building that needs to be built on the farm for this animal to be available to purchase. Buildings that are upgraded from this building are valid too. Default none. UnlockCondition (Optional) A game state query which indicates whether the farm animal is available in the shop menu. Default always unlocked. ShopDisplayName (Optional) A tokenizable string for the display name shown in the shop menu. Defaults to the DisplayName field. ShopDescription (Optional) A tokenizable string for the tooltip description shown in the shop menu. Defaults to none. ShopMissingBuildingDescription (Optional) A tokenizable string which overrides ShopDescription if the RequiredBuilding isn't built. Defaults to none. AlternatePurchaseTypes (Optional) The possible variants for this farm animal (e.g. chickens can be Brown Chicken, Blue Chicken, or White Chicken). This consists of a list of models with these fields: field effect AnimalIDs A list of animal IDs to spawn instead of the main ID field. If multiple are listed, one is chosen at random on purchase. Condition (Optional) A game state query which indicates whether this variant entry is available. Default always enabled. If multiple are listed, the first available variant is returned. Default none.
Hatching
field effect EggItemIds (Optional) A list of the object IDs that can be placed in the incubator or ostrich incubator to hatch this animal. If the animal's House field doesn't match the current building, the entry will be ignored. Default none. IncubationTime (Optional) How long eggs incubate before they hatch. Default 9000 minutes. IncubatorParentSheetOffset (Optional) An offset applied to the incubator's sprite index when it's holding an egg. Default 1. The vanilla values are:
offset incubator ostrich incubator 0 empty incubator empty incubator 1 small white egg large brown egg 2 small brown egg invalid (will show Junimo chest sprite) BirthText (Optional) A tokenizable string for the message shown when entering the building after the egg hatched. Defaults to the text "???". Growth
field effect DaysToMature (Optional) The number of days until a freshly purchased/born animal becomes an adult and begins producing items. Default 1. CanGetPregnant (Optional) Whether an animal can produce a child (regardless of gender). Default false. Produce
field effect ProduceItemIds
DeluxeProduceItemIds(Optional) The items produced by the animal when it's an adult. The DeluxeProduceItemIds field only applies if the Deluxe* fields match. Both default to none. This consists of a list of models with these fields:
field effect ItemId The unqualified object ID of the item to produce. Condition (Optional) A game state query which indicates whether this item can be produced now. Defaults to always true. MinimumFriendship (Optional) The minimum friendship points with the animal needed to produce this item. Default 0. If multiple items can be produced, one is chosen at random (with deluxe items taking priority if applicable).
DaysToProduce (Optional) The number of days between item productions. For example, setting 1 will produce an item every other day. Default 1. ProduceOnMature (Optional) Whether an item is produced on the day the animal becomes an adult. Default false. FriendshipForFasterProduce (Optional) The minimum friendship points needed to reduce the DaysToProduce by one. Defaults to no reduction based on friendship. DeluxeProduceMinimumFriendship (Optional) The minimum friendship points needed to produce the DeluxeProduceItemId. Default 200. DeluxeProduceCareDivisor
DeluxeProduceLuckMultiplier(Optional) Quantity modifiers which change the probability of producing the DeluxeProduceItemId, based on this formula: if happiness > 200: happiness_modifier = happiness * 1.5 else if happiness > 100: happiness_modifier = 0 else happiness_modifier = happiness - 100 ((friendship + happiness_modifier) / DeluxeProduceCareDivisor) + (daily_luck * DeluxeProduceLuckMultiplier)
Specifically:
- DeluxeProduceCareDivisor reduces the bonus from friendship and happiness, so a lower value increases the probability of producing the deluxe item. Default 1200.
- DeluxeProduceLuckMultiplier increases the effect of daily luck. Default 0.
For example, given a friendship of 102 and happiness of 150, the probability with the default field values will be
((102 + 0) / 1200) + (daily_luck * 0) = (102 / 1200) = 0.085
or 8.5%.See Animals#Produce for more info on the calculation.
HarvestType (Optional) How produced items are collected from the animal. The valid values are: value effect DropOvernight The item is placed on the ground in the animal's home building overnight. HarvestWithTool The item is collected from the animal directly based on the HarvestTool field. Default DropOvernight.
HarvestTool (Optional) The tool ID with which produced items can be collected from the animal, if the HarvestType is set to HarvestWithTool. The values recognized by the vanilla tools are MilkPail and Shears. Default none. Audio & sprite
field effect Sound (Optional) The audio cue ID for the sound produced by the animal (e.g. when pet). Default none. BabySound (Optional) Overrides Sound field when the animal is a baby. Has no effect if Sound isn't specified. Default none. Texture (Optional) The asset name for the animal's spritesheet. Defaults to Animals/ <ID>
(like Animals/Goat for a goat).HarvestedTexture (Optional) Overrides Texture if the animal doesn't currently have an item ready to collect (like the sheep's sheared sprite). Default none. BabyTexture (Optional) Overrides Texture and HarvestedTexture when the animal is a baby. Default none. UseFlippedRightForLeft (Optional) When the animal is facing left, whether to use a flipped version of their right-facing sprite. Default false. SpriteWidth
SpriteHeight(Optional) The pixel height & width of the animal's sprite (before the in-game pixel zoom). Both default to 16. EmoteOffset (Optional) A pixel offset to apply to emotes from the farm animal, specified as an object with X and Y. Default zero. Skins (Optional) A list of alternate appearances. If specified, a skin is chosen at random when the animal is purchased or hatched. This consists of a list of models with these fields: field effect ID A key which uniquely identifies the skin for this animal type. The ID should only contain alphanumeric/underscore/dot characters. For custom skins, this should be prefixed with your mod ID like Example.ModId_SkinName. Weight (Optional) A multiplier for the probability to choose this skin when an animal is purchased. For example, 2.0 will double the chance this skin is selected relative to the other skins. Default 1.0. Texture
HarvestedTexture
BabyTexture(Optional) Overrides the equivalent main field when this skin is selected. Defaults to the main field's value. ShadowWhenBaby
ShadowWhenBabySwims
ShadowWhenAdult
ShadowWhenAdultSwims(Optional) The shadow to draw under the farm animal. The Baby fields only apply when the farm animal is a baby, and Adult fields only applies when it's an adult (e.g. a baby animal won't default to the adult fields). When the farm animal swims, it'll use the Swims variant if it's set, else default to the non-swim variant. These consist of a model with these fields:
field effect Visible (Optional) Whether the shadow should be drawn. Default true. Offset (Optional) A pixel offset applied to the shadow position, specified as an object with X and Y fields. Default zero. Scale (Optional) The scale at which to draw the shadow. Default 2.5 (swimming baby), 3 (baby), 3.5 (swimming adult), or 4 (adult). Player profession effects
field effect ProfessionForFasterProduce (Optional) The internal ID of a profession which reduces the DaysToProduce by one. Default none. ProfessionForHappinessBoost (Optional) The internal ID of a profession which makes it easier to befriend this animal. Default none. ProfessionForQualityBoost (Optional) The internal ID of a profession which increases the chance of higher-quality produce. Default none. Behavior
field effect CanSwim (Optional) Whether animals on the farm can swim in water once they've been pet. Default false. BabiesFollowAdults (Optional) Whether baby animals can follow nearby adults. Default false. GrassEatAmount (Optional) The amount of grass eaten by this animal each day. Default 2. HappinessDrain (Optional) An amount which affects the daily reduction in happiness if the animal wasn't pet, or didn't have a heater in winter. Default none. Price (Optional) The price when the player sells the animal, before the friendship boost. Default 0. CustomFields The custom fields for this entry. Other
field effect ShowInSummitCredits (Optional) Whether to show the farm animal in the credit scene on the summit after the player achieves perfection. Default false. StatToIncrementOnProduce (Optional) The game stat counters to increment when the animal produces an item. Default none. This consists of a list of models with these fields: field effect StatName The name of the stat counter field on Game1.stats. RequiredTags (Optional) A comma-delimited list of context tags required on the main input item. The stat is only incremented if the item has all of these. You can negate a tag with ! (like bone_item,!fossil_item
for bone items that aren't fossils). Defaults to always enabled.UpDownPetHitboxTileSize
LeftRightPetHitboxTileSize(Optional) The animal sprite's tile size in the world when the player is clicking to pet them, specified in the form <width>
,<height>
. The UpDownPetHitboxTileSize applies when the animal is facing up or down, and LeftRightPetHitboxTileSize applies when facing left or right. The values can be fractional (e.g. cows have a width of 1.75). Both default to a 1×1 tile.BabyUpDownPetHitboxTileSize
BabyLeftRightPetHitboxTileSize(Optional) Overrides UpDownPetHitboxTileSize and LeftRightPetHitboxTileSize respectively before the animal is an adult. Both default to 1×1 tile. Custom pets
Format
You can now create and customize pets & pet breeds by editing the new Data/Pets asset.
This consists of a string → model lookup, where...
- The key is a unique identifier for the pet (not the pet breed). The vanilla IDs are Cat and Dog. For custom pets, this should be prefixed with your mod ID like Example.ModId_PetName.
- The value is a model with the fields listed below.
Basic info
field effect DisplayName A tokenizable string for the pet type's display name (e.g. "cat" or "dog"). For example, the vanilla adoption events show this when Marnie asks if you want to adopt the cat/dog. Audio & sprites
field effect BarkSound The cue ID for the pet's occasional 'bark' sound. ContentSound The cue ID for the sound which the pet makes when you pet it. RepeatContentSoundAfter (Optional) The number of milliseconds until the ContentSound is repeated once. This is used by the dog, who pants twice when pet. Defaults to -1 (disabled). EmoteOffset (Optional) A pixel offset for the emote drawn above the pet sprite, specified as an object with X and Y fields. For example, this affects the heart emote shown after petting it. Default none. Events
field effect EventOffset (Optional) The pixel offset for the pet when shown in events like Marnie's adoption event, specified as an object with X and Y fields. Default none. AdoptionEventLocation
AdoptionEventId(Optional) If both fields are set, the location and event ID which lets the player adopt this pet. This forces the event to play after 20 days if its preconditions haven't been met yet. Default Farm and none respectively. SummitPerfectionEvent (Optional) How to render the pet during the summit perfection slideshow. If this isn't set, the pet won't be shown in the slideshow. This consists of a model with these fields:
field effect SourceRect The source rectangle within the pet's texture to draw. AnimationLength The number of frames to show starting from the SourceRect. Motion The motion to apply to the pet sprite. Flipped (Optional) Whether to flip the pet sprite left-to-right. Default false. PingPong (Optional) Whether to apply the 'ping pong' effect to the pet sprite animation. Default false. Behavior
field effect MoveSpeed (Optional) How quickly the pet can move. Default 2. SleepOnBedChance
SleepNearBedChance
SleepOnRugChance(Optional) The percentage chances for the locations where the pet will sleep each night, as a decimal value between 0 (never) and 1 (always). Each value is checked in the order listed at left until a match is found. If none of them match, the pet will choose a random empty spot in the farmhouse; if none was found, it'll sleep next to its pet bowl outside. Behaviors The pet's possible actions and behaviors, defined as the states in a state machine. Essentially the pet will be in one state at any given time, which also determines which state they can transition to next. For example, a cat can transition from Walk to BeginSitDown, but it can't skip instantly from Walk to SitDownLick. This consists of a list of models with these fields:
- Required fields:
-
field effect Name A unique name for the state. This only needs to be unique within the pet type (e.g. Cat and Dog can have different behaviors with the same name). - Direction:
-
field effect Direction (Optional) The specific direction to face at the start of this state (one of left, right, up, or down), unless overridden by RandomizeDirection. RandomizeDirection (Optional) Whether to point the pet in a random direction at the start of this state (overriding the Direction if specified). Default false. IsSideBehavior (Optional) Whether to constrain the pet's facing direction to left and right while the state is active. Default false. - Movement:
-
field effect WalkInDirection (Optional) Whether to walk in the pet's facing direction. Default false. MoveSpeed (Optional) Overrides the pet's MoveSpeed field while this state is active. Default -1 (which uses the pet's MoveSpeed value). - Audio:
-
field effect SoundOnStart (Optional) The audio cue ID for the sound to play when the state starts. If set to BARK, the pet's BarkSound (or breed's BarkOverride) field is used. Defaults to none. SoundRange
SoundRangeFromBorder(Optional) When set, the SoundOnStart is only audible if the pet is within this many tiles away from the player (SoundRange) or past the border of the screen (SoundRangeFromBorder). Default -1 (no distance check). SoundIsVoice (Optional) Whether to mute the SoundOnStart when the 'mute animal sounds' option is set. Default false. - Behavior transitions:
-
field effect AnimationEndBehaviorChanges
TimeoutBehaviorChanges
PlayerNearbyBehaviorChanges
RandomBehaviorChanges
JumpLandBehaviorChanges(Optional) A list of possible behavior transitions to start when the criteria are achieved. If multiple transitions are listed, a random one will be selected. If omitted, it won't affect behavior transitions. These are triggered when this behavior's animation finishes (AnimationEndBehaviorChanges), when the set duration ends (TimeoutBehaviorChanges), when the player is within 2 tiles of the pet (PlayerNearbyBehaviorChanges), randomly at the start of each frame based on the RandomBehaviorChangeChance field (RandomBehaviorChanges), and when the pet finishes a jump (JumpLandBehaviorChanges).
These consist of a list of models with these fields:
field effect Behavior
LeftBehavior
RightBehavior
UpBehavior
DownBehaviorThe name of the behavior to start. The pet will check for a behavior field matching its current facing direction first, then try the Behavior. If none are specified, the current behavior will continue unchanged. OutsideOnly (Optional) Whether the transition can only happen if the pet is outside. Default false. Weight (Optional) The option's weight when randomly choosing a behavior, relative to other behaviors in the list (e.g. 2 is twice as likely as 1). Default 1. Duration
MinimumDuration
MaximumDuration(Optional) The millisecond duration until the pet transitions to a behavior in the TimeoutBehaviorChanges field, if set. You must specify either a specific duration, or an inclusive minimum-to-maximum range in which the game will choose a random duration. If omitted, the behavior won't have a duration limit. RandomBehaviorChangeChance (Optional) The random probability at the start of each frame that the pet will transition to a behavior in the RandomBehaviorChanges field, if set. Specified as a value between 0 (never) and 1 (always). Default 0. - Animation and per-frame sounds:
-
field effect Animation (Optional) The animation frames to play while this state is active. This consists of a list of models with these fields: field effect Frame The frame index in the animation. This should be an incremental number starting at 0. Duration The millisecond duration for which the frame should be kept on-screen before continuing to the next frame. HitGround (Optional) Whether to play the footstep sound for the tile under the pet when the frame starts. Default false. Jump (Optional) Whether the pet should perform a small hop when the frame starts, including a 'dwop' sound. Default false. Sound (Optional) The audio cue ID for the sound to play when the animation starts or loops. If set to BARK, the pet's BarkSound (or breed's BarkOverride) field is used. Defaults to none. SoundRange
SoundRangeFromBorder
SoundIsVoiceSee description for the equivalent behavior fields, but applies to the frame's Sound field instead. Shake (Optional) The millisecond duration for which to shake the pet when the state starts. Default 0. LoopMode (Optional) What to do when the last animation frame is reached while the behavior is still active. The possible values are Hold (keep the last frame visible until the animation ends), Loop (restart from the first frame), or None (equivalent to Loop). Default None. AnimationMinimumLoops
AnimationMaximumLoops(Optional) The minimum and maximum number of times to play the animation. Both must be specified to have any effect. The game will choose an inclusive random value between them. Both default to -1 (don't repeat animation).
Breeds
field effect Breeds The cosmetic breeds which can be selected in the character customization menu when creating a save. This consists of a list of models with these fields: field effect ID The unique ID for the breed within the pet type. Texture The asset name for the breed spritesheet for the pet's in-game sprite. This should be 128 pixels wide, and 256 (cat) or 288 (dog) pixels high. IconTexture The asset name for the breed icon texture, shown on the character customization screen and in-game menu. This should be a 16x16 pixel icon. IconSourceRect The icon's pixel area within the IconTexture, specified as an object with X, Y, Width, and Height fields. BarkOverride (Optional) Override the pet's BarkSound field for this breed, if set. VoicePitch (Optional) The pitch applied to the pet's bark sound, measured as a decimal value relative to 1. Defaults to 1. Advanced
field effect CustomFields The custom fields for this entry. Other changes
- The pet bowl is now a building which can be constructed or moved. Each pet is assigned to an available pet bowl. For C# mods, each pet now has a guid field populated with a unique ID, and each pet bowl has a petGuid field which tracks its owner (see the PetBowl::HasPet() and PetBowl::FindPet() methods).
- In the event character setup, you can now use pet to add a pet of the player's selected type. Its actor name will be PetActor in other event commands. This supersedes cat (with name Cat) and dog (with name Dog), though those still work too.
- For C# mods:
- All pets now use a generic Pet class, instead of Cat or Dog. The pet type is tracked by the pet's petType field.
- The player's preferred pet type is tracked by Game1.player.whichPetType. The former catPerson field is now readonly and checks that field.
- Added Pet.type_cat and Pet.type_dog constants for the default pet types.
Custom monster eradication goals
- See also: Monster eradication goal flag changes.
You can now add/edit Adventurer's Guild monster eradication goals by editing the new Data/MonsterSlayerQuests data asset.
This consists of a string → model lookup, where...
- The key is a unique ID for the monster eradication goal. This ID should only contain alphanumeric/underscore/dot characters, and custom goal IDs should ideally be prefixed with your mod ID like Example.ModId_GoalName.
- The value is a model with the fields listed below.
field effect DisplayName A tokenizable string for the goal's display name, shown on the board in the Adventurer's Guild. Targets A list of monster IDs that are counted towards the Count. Count The total number of monsters (matching the Targets) which must be defeated to complete this goal. RewardItemId (Optional) The qualified ID for the item that can be collected from Gil when this goal is completed. Default none. RewardItemPrice (Optional) The price of the RewardItemId in Marlon's shop after the goal is completed, or -1 to disable buying it from Marlon. Default -1. RewardDialogue
RewardDialogueFlag(Optional) A tokenizable string for custom Gil dialogue shown when talking to him after completing the goal, and an optional mail flag to set when the player has seen the dialogue. Both default to none. If there are reward items, they're shown after this dialogue.
If RewardDialogue is used without RewardDialogueFlag, then this dialogue will be shown each time the reward menu is opened after completing the goal, until the player collects the reward items. If the RewardItems isn't set, this can safely be omitted since the goal will be marked collected immediately.
This doesn't send a letter; see RewardMail or RewardMailAll for that.
RewardFlag
RewardFlagAll(Optional) The mail flag ID to set for the current player (RewardFlag) or all players (RewardFlagAll) when talking to Gil after completing the goal. Default none. Note that RewardFlag is usually not needed, since the game will also set a Gil_
<goal ID>
flag regardless.This doesn't send a letter; see RewardMail or RewardMailAll for that.
RewardMail
RewardMailAll(Optional) The mail letter ID to add to the mailbox tomorrow for the current player (RewardMail) or all players (RewardMailAll). Default none. CustomFields The custom fields for this entry. Custom phone calls
Mods can now extend the telephone with custom calls (both incoming calls, and phone numbers which the player can call).
Incoming calls
You can add or customize incoming calls by editing the Data/IncomingPhoneCalls asset.
This consists of a string → model lookup, where...
- The key is a unique call ID. This should only contain alphanumeric/underscore/dot characters, and custom entries should be prefixed with your mod ID like Example.ModId_CallId.
- The value is a model with the fields listed below.
field effect Dialogue The dialogue text to show when the player answers the phone. This can use the full dialogue format (including questions and different dialogue based on the selected answer). FromNpc (Optional) The internal name of the NPC making the call. If specified, that NPC's name and portrait will be shown. FromPortrait (Optional) The asset name for the portrait spritesheet to display (like Portraits/Abigail). If FromNpc is specified too, this overrides the portrait from that NPC. If both FromNpc and FromDisplayName are null, this portrait will be shown with the display name "???". FromDisplayName (Optional) A tokenizable string for the calling NPC's display name. If FromNpc is specified too, this overrides the display name from that NPC. MaxCalls (Optional) The maximum number of times a player can receive this phone call, or <c>-1 for no limit. Default 1. TriggerCondition
RingCondition(Optional) If set, a game state query which indicates whether to trigger this phone call (TriggerCondition) or whether the phone rings when this call is received (RingCondition). Whether a player receives this call depends on both fields: TriggerCondition is checked on the main player before sending the call to all players, then RingCondition is checked on each player to determine whether the phone rings for them.
IgnoreBaseChance (Optional) Whether to ignore the 1% base chance when checking whether to trigger an incoming call. If true, the game will check if this call can be received regardless of the base chance. Default false. SimpleDialogueSplitBy (Optional, specialized) If set, marks the call as having a simple dialogue string without an NPC name and portrait, with lines split into multiple boxes by this substring. For example, "SimpleDialogueSplitBy": "#"
will splitBox A#Box B#Box C
into three consecutive dialogue boxes.You should omit this in most cases, and use the regular dialogue format in Dialogue to split lines if needed. This is mainly intended to support some older vanilla phone calls.
CustomFields The custom fields for this entry. Custom handlers in C#
C# mods can implement StardewValley.PhoneCalls.IPhoneHandler and add it to Phone.PhoneHandlers for full control over both incoming and outgoing calls:
/// <summary>The mod entry point.</summary> internal class ModEntry : Mod { /// <inheritdoc /> public override void Entry(IModHelper helper) { Phone.PhoneHandlers.Add(new CustomPhoneHandler()); } } /// <summary>A custom phone handler.</summary> internal class CustomPhoneHandler : IPhoneHandler { ... }
See StardewValley.PhoneCalls.DefaultPhoneHandler in the decompiled game code for an example implementation.
Custom shops
Format
You can now create and edit shops via the new Data/Shops asset. This consists of a string → model lookup, where the key is a unique ID for the shop (using a globally unique ID which includes your mod ID like ExampleMod.Id_ShopName for custom shops), and the value is a model with these fields:
field effect Items The items to add to the shop inventory. This consists of a list of values with these fields: field effect common fields See item spawn fields for the generic item fields supported by shop items. Notes:
- If set to an item query which returns multiple items, all of them will be added to the shop.
- The MinStack and MaxStack fields apply to the item after it's purchased, and have no effect on the price or Stock limit.
- If the player found Pierre's Missing Stocklist, season conditions in the Condition field are ignored in Pierre's General Store.
Price (Optional) The gold price to purchase the item from the shop. Defaults to the item's normal price, or zero if TradeItemId is specified. TradeItemId
TradeItemAmount(Optional) The qualified or unqualified item ID and amount which must be traded to purchase this item. Defaults to no item and 1 respectively. If both Price and TradeItemId are specified, the player will have to provide both to get the item.
ApplyProfitMargins (Optional) Whether to multiply the price by the difficulty modifier, which reduces the price for higher profit margins. This can be true (always apply it), false (never apply it), or null (apply for certain items like saplings). This is applied before any quantity modifiers. Default null. IgnoreShopPriceModifiers (Optional) Whether to ignore the shop's PriceModifiers field for this item. This has no effect on the item's equivalent field. Default false. AvailableStockModifiers
PriceModifiers(Optional) Quantity modifiers applied to the AvailableStock or Price values. Notes:
- The price modifiers stack with the PriceModifiers field on the shop (unless IgnoreStorePriceModifiers is true).
AvailableStockModifierMode
PriceModifierMode(Optional) quantity modifier modes which indicate what to do if multiple modifiers in the AvailableStockModifiers or PriceModifiers field apply at the same time. Default Stack. AvoidRepeat (Optional) Whether to avoid adding this item to the shop if it would duplicate one that was already added. If the item ID is randomized, this will choose a value that hasn't already been added to the shop if possible. Default false. AvailableStock (Optional) The maximum number of the item which can be purchased in one day. Default unlimited. AvailableStockLimit (Optional) If Stock is set, how the limit is applied in multiplayer. This has no effect on recipes. The possible values are:
value effect Global The limit is shared by every player in the world. For example, if the Stock was 1 and a player bought it, no other players could buy one. Player The limit applies to each player separately. For example, if the Stock was 1, each player could buy one. None The limit applies to the current instance of the shop menu. If you exit and reopen the menu, the item will reappear with the same stock. This is mainly used for items that are added conditionally. Default Global.
SalableItemTags (Optional) A list of context tags for items which the player can sell to to this shop. Default none. Owners (Optional) The portrait and dialogue to show in the shop menu UI. When the Action OpenShop tile property specifies
[owner tile area]
, the first NPC within the tile area which matches an owner entry is used; if no NPCs match, the shop isn't opened. If Owners is omitted, the shop is opened regardless of whether an NPC is present, and no portrait or dialogue is shown.This consists of a list of models with these fields:
field effect Name One of... - the internal name for the NPC who must be in range to use this entry;
- AnyOrNone to use this entry regardless of whether any NPC is within the shop area;
- Any to use this entry if any NPC is within the shop area;
- None to use this entry if no NPC is within the shop area.
Id (Optional) An ID for this entry within the shop. This only needs to be unique within the current shop's owner list. Defaults to the Name value. Condition (Optional) A game state query which indicates whether this owner entry is available. If omitted, it's always available. Portrait (Optional) One of... - the internal name of the NPC whose portrait to show;
- the asset name of the portrait spritesheet to display.
If omitted, defaults to the portrait for the NPC matching the Name field (if any). If set to a value which doesn't match an NPC or texture asset name, the portrait is disabled.
Dialogues (Optional) A list of possible dialogues if this entry is selected. Each day one dialogue will be randomly chosen to show in the shop UI. Each dialogue consists of a model with these fields: field effect Id An ID for this dialogue. This only needs to be unique within the current dialogue list. For a custom entry, you should use a unique ID which includes your mod ID like <samo>ExampleMod.Id_DialogueName. Dialogue The dialogue text to show, as a tokenizable string. The resulting text is parsed using the dialogue format. RandomDialogue (Optional) A list of dialogue texts to randomly choose from, using the same format as Dialogue. If set, Dialogue is optional and ignored. Each entry in the list has an equal probability of being chosen, and the choice is persisted for the current day. For example: "RandomDialogue": [ "[LocalizedText Strings\StringsFromCSFiles:ShopMenu.cs.11469]", "[LocalizedText Strings\StringsFromCSFiles:ShopMenu.cs.11470]", "[LocalizedText Strings\StringsFromCSFiles:ShopMenu.cs.11471]" ]
Condition (Optional) A game state query which indicates whether the dialogue should be available. If omitted, the dialogue is always available. This can be set to an empty list (
"Dialogues": []
) to disable the dialogue text entirely. If omitted, defaults to a generic "Have a look at my wares" text.RandomizeDialogueOnOpen (Optional) If Dialogues has multiple matching entries, whether to re-randomize which one is selected each time the shop is opened (true) or once per day (false). Currency (Optional) The currency in which all items in the shop should be priced. The valid values are 0 (money), 1 (star tokens), 2 (Qi coins), and 4 (Qi gems). Default 0. For item trading, see TradeItemId for each item. ApplyProfitMargins (Optional) The default value for ApplyProfitMargins under Items, if set. This can be true (always apply it), false (never apply it), or null (apply for certain items like saplings). This is applied before any quantity modifiers. Default null. StackSizeVisibility (Optional) How to draw stack size numbers in the shop list by default. If omitted, the default shop logic is applied (usually equivalent to Show). The possible values are:
value effect Hide Always hide the stack size. Show Always draw the stack size. ShowIfMultiple Draw the stack size if it's more than one. This is ignored in some special cases (e.g. recipes can't have a stack size).
OpenSound (Optional) The audio cue ID to play when the shop menu is opened. Defaults to dwop. PurchaseSound (Optional) The audio cue ID to play when an item is purchased normally. Defaults to purchaseClick. purchaseRepeatSound (Optional) The audio cue ID to play when accumulating a stack to purchase (e.g. by holding right-click on PC). Defaults to purchaseRepeat. PriceModifiers (Optional) Quantity modifiers applied to the sell price for items in this shop. See also PriceModifiers under Items. PriceModifierMode (Optional) A quantity modifier mode which indicates what to do if multiple modifiers in the PriceModifiers field apply at the same time. This only affects that specific field, it won't affect price modifiers under Items. Default Stack. VisualTheme (Optional) The visual theme to apply to the shop UI, or omit to use the default theme. The first matching theme is applied. All fields are optional and will fallback to the default theme. This consists of a list of models with these fields:
field effect Condition (Optional) A game state query which indicates whether this theme should be applied. Defaults to always true. WindowBorderTexture
WindowBorderSourceRect(Optional) The texture asset name, and the pixel area within it, for the shop window border. Defaults to LooseSprites\Cursors at (384, 373) with size 18×18. PortraitBackgroundTexture
PortraitBackgroundSourceRect(Optional) The texture asset name, and the pixel area within it, for the NPC portrait background. Defaults to LooseSprites\Cursors at (603, 414) with size 74×74. DialogueBackgroundTexture
DialogueBackgroundSourceRect(Optional) The texture asset name, and the pixel area within it, for the NPC dialogue background. Defaults to Maps\MenuTiles at (0, 256) with size 60×60. DialogueColor
DialogueShadowColor(Optional) The sprite text color for the dialogue text. See color format. Defaults to the game's standard text color. ItemRowBackgroundTexture
ItemRowBackgroundSourceRect(Optional) The texture asset name, and the pixel area within it, for the item row background in the shop inventory. Defaults to LooseSprites\Cursors at (384, 396) with size 15×15. ItemRowBackgroundHoverColor (Optional) The color tint to apply to the item row background in the shop inventory when the cursor is hovering over it, or White for no tint. See color format. Defaults to Wheat. ItemRowTextColor (Optional) The sprite text color for the item text. See color format. Defaults to the game's standard text color. ItemIconBackgroundTexture
ItemIconBackgroundSourceRect(Optional) The texture asset name, and the pixel area within it, for the background behind the item icons. Defaults to LooseSprites\Cursors at (296, 363) with size 18×18. ScrollUpTexture
ScrollUpSourceRect(Optional) The texture asset name, and the pixel area within it, for the up arrow icon above the scrollbar. Defaults to LooseSprites\Cursors at (421, 459) with size 11×12. ScrollDownTexture
ScrollDownSourceRect(Optional) The texture asset name, and the pixel area within it, for the down arrow icon beneath the scrollbar. Defaults to LooseSprites\Cursors at (421, 472) with size 11×12. ScrollBarFrontTexture
ScrollBarFrontSourceRect(Optional) The texture asset name, and the pixel area within it, for the sliding scrollbar foreground. Defaults to LooseSprites\Cursors at (435, 463) with size 6×10. ScrollBarBackTexture
ScrollBarBackSourceRect(Optional) The texture asset name, and the pixel area within it, for the scrollbar background. Defaults to LooseSprites\Cursors at (403, 383) with size 6×6. CustomFields The custom fields for this entry. Open a custom shop
You can place an Action OpenShop tile property on the map, which will open the given shop ID when the player clicks it.
In C# code, you can get the inventory for a custom shop using
Utility.GetShopStock("shop id here")
, open a shop menu usingUtility.OpenShopMenu("shop id", …)
, and add temporary items to an open menu usingshopMenu.AddForSale(…)
. The ID of the opened shop is stored in the shop menu's storeContext field.Examples
You can add or replace entire shops. For example, this content pack adds a shop that sells ice cream in summer, and pufferfish all year:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/Shops", "Entries": { "Example.ModId_CustomShop": { "Owners": [ { "Name": "Any", "Dialogues": [ // dialogue on sunny summer days { "Id": "Example.ModId_SunnySummer", "Condition": "SEASON Summer, WEATHER Here Sun", "Dialogue": "Ice-cream is perfect for a day like this." }, // dialogue any other time { "Id": "Example.ModId_Default", "Dialogue": "Welcome to the only place in town for pufferfish!" } ] } ], "Items": [ // ice-cream in summer, default price { "Id": "Example.ModId_IceCream", "Condition": "SEASON Summer", "ItemId": "(O)233" }, // pufferfish for 1000g, limited to one per day per player { "Id": "Example.ModId_PufferFish", "ItemId": "(O)128", "Price": 1000, "AvailableStock": 1, "AvailableStockLimit": "Player" } ] } } } ] }
You can also add, replace, edit, or reorder items in a specific shop by targeting the shop's Items field. For example, this removes Trout Soup (item #219) and adds Pufferfish above bait (item #685):
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/Shops", "TargetField": [ "FishShop", "Items" ], "Entries": { "(O)219": null, "Example.ModId_Pufferfish": { "Id": "Example.ModId_Pufferfish", "ItemId": "(O)128", "Price": 2000 } }, "MoveEntries": [ { "Id": "Example.ModId_Pufferfish", "BeforeId": "(O)685" } ] } ] }
Vanilla shop IDs
Vanilla shops are now defined in Data/Shops too (except a few special cases like dressers and home renovations).
See Data/Shops for a full list, but here are the main shop IDs for convenience:
shop ID Abandoned house shop HatMouse Adventurer's Guild AdventureShop (regular shop)
AdventureGuildRecovery (item recovery service)Casino Casino Clint's blacksmith shop Blacksmith (regular shop)
ClintUpgrade (tool upgrades)Desert trader DesertTrade Dwarf's shop Dwarf Harvey's clinic Hospital Ice-cream stand IceCreamStand Island resort ResortBar Island trader IslandTrade Joja Mart Joja Krobus' shop ShadowShop Marnie's ranch AnimalShop Pierre's general store SeedShop Robin's carpenter shop Carpenter Stardrop Saloon Saloon Sandy's Oasis shop Sandy Traveling cart Traveler Willy's fish shop FishShop Festival shops are also defined in Data/Shops now, though they can still be defined in the pre-1.6 way for backwards compatibility.
festival shop ID Dance of the Moonlight Jellies Festival_DanceOfTheMoonlightJellies_Pierre Egg Festival Festival_EggFestival_Pierre Festival of Ice Festival_FestivalOfIce_TravelingMerchant Feast of the Winter Star Festival_FeastOfTheWinterStar_Pierre Flower Dance Festival_FlowerDance_Pierre Luau Festival_Luau_Pierre Night Market (decoration boat) Festival_NightMarket_DecorationBoat Night Market (magic boat) Festival_NightMarket_MagicBoat_Day1
Festival_NightMarket_MagicBoat_Day2
Festival_NightMarket_MagicBoat_Day3Spirit's Eve Festival_SpiritsEve_Pierre Stardew Valley Fair Festival_StardewValleyFair_StarTokens And two special 'shops':
item ID Catalogue Catalogue Furniture Catalogue Furniture Catalogue Dialogue changes
- Added new dialogue commands:
command description $f <response IDs>
Forget any number of space-delimited dialogue response IDs previously answered by the player. $v <event id>
[check preconditions]
[skip if seen]
Immediately start an event and end the current dialogue, subject to the conditions: [check preconditions]
: whether to ignore the command if the event's preconditions don't match (one of true or false). Default true.[skip if seen]
: whether to ignore the command if the player has already seen the given event. Default true.
If the event is skipped, the dialogue continues to the next line instead.
For example,
$v 60367 false false
will replay the bus arrival event from the start of the game. - Dialogue response IDs are now strings, so mods can use a unique key like Example.ModId_ResponseName (instead of hoping no other mod uses the same number). Prefixing the mod ID is recommended to simplify troubleshooting and avoid conflicts. For best compatibility, custom IDs should only contain alphanumeric/underscore/dot characters.
- Item spawn codes can now spawn any item type by using the qualified item ID, like
[(F)1664]
for a Mystic Rug. - For C# mods, Dialogue now tracks the translation key used to build it (when applicable). For example, you can detect when the player is rejected at the Flower Dance (derived from Three-Heart Dance Partner):
private void OnMenuChanged(object sender, MenuChangedEventArgs e) { bool isDanceRejection = Game1.currentLocation?.currentEvent?.FestivalName == "Flower Dance" && e.NewMenu is DialogueBox dialogueBox && dialogueBox.characterDialogue is {} dialogue && dialogue.TranslationKey == $"Characters\\Dialogue\\{dialogue.speaker?.Name}:danceRejection"; }
For C# mods that create Dialogue instances directly, there's a few ways to do it now:
// from a translation key var dialogue = new Dialogue(npc, "Strings\\StringsFromCSFiles:Utility.cs.5360"); // from custom text (with or without a translation key) var dialogue = new Dialogue(npc, null, "Some arbitrary text to show as-is"); // from a translation with tokens var dialogue = Dialogue.FromTranslation(npc, "Data\\ExtraDialogue:PurchasedItem_2_QualityLow_Willy", whatToCallPlayer, particle, i.DisplayName);
You can also easily add fallback logic using Dialogue.TryGetDialogue or npc.TryGetDialogue. For example:
Dialogue dialogue = npc.TryGetDialogue($"rejection_{itemId}_{locationName}_{x}_{y}") ?? npc.TryGetDialogue($"rejection_{itemId}_{locationName}") ?? npc.TryGetDialogue($"rejection_{itemId}") ?? new Dialogue(npc, "Strings\\StringsFromCSFiles:NPC.cs.3971");
- The reject_
<item id>
dialogue key now also works with movie tickets, void ghost pendants, bouquets, wilted bouquets, and mermaids' pendants. - The 'reveal taste' dialogue command now uses the format %revealtaste:
<npc name>
:<item ID>
to support item IDs. (The previous %revealtaste<npc name>
<item index>
format still works to support old content packs, but the item index can only be a number.) - Fixed unknown dialogue commands starting with $ being parsed as a portrait number when not numeric.
- Fixed NPCs only using a
{day name}{hearts}_{year}
dialogue if they also have a{day name}{hearts}
one. - Fixed NPCs only using the
MovieInvitation
dialogue key in English.
Schedule changes
- Schedule keys are now case-insensitive.
- Added a new
<day of week>
_<min hearts>
schedule key. - Added an NPC.ScheduleKey field which always matches their loaded schedule.
- Schedule commands now trim surrounding whitespace, so they can be multilined for readability. For example:
"Wed": " 1000 ArchaeologyHouse 11 9 0/ 1800 Town 47 87 0/ 2200 SeedShop 1 9 3 abigail_sleep "
- Removed an unintended schedule fallback to a {season}_spring_{hearts} key. It'll skip to the spring default instead.
- Schedules are now fault-tolerant:
- Fixed crash if a selected schedule can't be parsed. The NPC now logs an error and continues with the next fallback instead.
- Fixed crash if certain hardcoded schedules aren't present (like Penny's marriageJob or Pam's bus).
- Fixed error if a schedule command is empty.
- For C# mods, removed the dayOfMonth parameter in NPC.getSchedule(). This was misleading since it used Game1.dayOfMonth in all but one line regardless.
Other NPC changes
- Added Game1.characterData and Game1.farmAnimalData to read NPC/animal info without constantly reloading the Data/Characters or Data/FarmAnimals asset.
- All translated NPC names are now in Strings/NPCNames.
- Added new fields & methods for C# mods:
type field/method effect AdventureGuild IsComplete(data) Get whether an Adventurer's Guild monster eradication goal has been completed, regardless of whether the player collected its rewards yet. HasCollectedReward(player, id) Get whether a given player has completed an Adventurer's Guild monster eradication goal and collected its rewards. For example: bool isPhoneUnlocked = AdventureGuild.HasCollectedReward(Game1.player, "Gil_FlameSpirits");
AnimalHouse adoptAnimal Add an animal to this location and set the location as the animal's home. Character GetGender Get the character's gender as one of the numeric constants (NPC.female, NPC.male, or NPC.undefined). This returns the specific gender for players, villager NPCs, and children; other NPCs (like monsters) return NPC.undefined. FarmAnimal isAdult Get whether the farm animal is fully grown (opposite of isBaby()). CanGetProduceWithTool Get whether the farm animal's produce can be collected with a given tool (e.g. milk pail for a cow). CanLiveIn Get whether the animal can be added to a building. GetDisplayName
GetShopDescriptionGet the translated display name or shop description for this animal. GetHarvestType Get whether the animal's produce is dropped or collected with a tool. growFully Instantly age the animal to adulthood if it's still a baby. ReloadTextureIfNeeded Update the animal sprite based on the current state + data. Farmer GetDisplayPants
GetDisplayShirtGet the texture and sprite index to draw for the player's pants or shirt. This accounts for override clothing, worn clothing, and the default clothing drawn when the farmer isn't wearing anything. For example:
Game1.player.GetDisplayShirt(out Texture2D texture, out int spriteIndex);
CanDyePants
CanDyeShirtGet whether the currently equipped pants or shirt can be dyed. WearTemporaryWeddingAttire
RemoveTemporaryWeddingAttireTemporarily change the player into or out of their wedding attire. The default logic changes male farmers into the tuxedo, and has no effect on female farmers. NPC CanReceiveGifts Get whether this NPC can receive gifts from the player (regardless of whether they've already received one today). GetData
NPC.TryGetDataGet the underlying data from Data/Characters for this NPC, if any. NPC.GetDisplayName(name) Get the translated display name in the current language for an NPC by their internal name. hasDarkSkin Whether this character has dark skin for the purposes of child genetics. Pet GetPetData
TryGetDataGet the underlying data from Data/Pets for this pet, if any. ShopMenu ShopId A key which identifies the current shop. This may be the unique shop ID in Data/Shops for a standard shop, Dresser or FishTank for furniture, etc. This is guaranteed to be set to a relevant shop ID. This replaces the former shopContext field, and will usually have the same value in cases where that was set to a unique shop ID.
Utility getAllVillagers Get all villager NPCs (excluding horses, pets, monsters, player children, etc). This works just like getAllCharacters with an added filter. - NPCs now update on save loaded when their home data changes.
- NPC.reloadSprite() now has an argument to only reload the appearance, without changing other data.
- Utility.getAllCharacters() now returns a plain List<NPC> value instead of a custom DisposableList<NPC>, so you can use normal LINQ querying on it.
- Utility.GetHorseWarpRestrictionsForFarmer(player) now returns an enum (which is more efficient and easier for mods to patch), and added a new Utility.GetHorseWarpErrorMessage(restrictions) method to get the error message to show for it.
- Farmer.hasAFriendWithHeartLevel now has an optional max-hearts argument.
- Removed most FarmAnimal fields/properties which just mirror the underlying data.
- Fixed child NPCs like Jas or Vincent ignoring relative titles like "mom" in Data/NPCDispositions (now Data/Characters) for reveal-gift-taste dialogues.
- Fixed custom NPCs ignoring dialogue when they use a subclass of NPC.
- Fixed monsters not loading their display name from Data/Monsters for English players.
- Fixed player children not applying the IsInvisible flag.
What's new for everything else
Buff overhaul
1.6 rewrites buffs to work more consistently and be more extensible:
- Buff logic is unified into Game1.player.buffs, which is the single source of truth for buff data. This replaces the previous player.added* and player.appliedBuffs fields, BuffsDisplay logic, enchantment stat bonuses, and boots/ring attribute changes on (un)equip.
- This also removes limitations on buff types (e.g. buffs can add weapon bonuses and weapons can add attribute buffs) and buffable equipment (e.g. equipped tools can have buffs too).
- Buff effects are now fully recalculated when they change, to fix a range of longstanding bugs like attribute drift and double-debuffs. Just like before, the buffs are managed locally; only the buff IDs and aggregate attribute effects are synced.
For C# mods:
- Each buff now has a unique string ID. You can apply a new buff with the same ID to replace it (so you no longer need to manually find and remove previous instances of the buff).
- You can add standard buff effects to any equipment by overriding Item.AddEquipmentEffects, or add custom behaviour/buffs by overriding Item.onEquip and Item.onUnequip.
- You can add custom food or drink buffs by overriding Item.GetFoodOrDrinkBuffs().
- The Buff constructor now supports a custom icon texture, sprite index, display name, description, and millisecond duration to fully support custom buffs.
- You can change how buff attributes are displayed (or add new attributes) by extending the BuffsDisplay.displayAttributes list.
For example, here's how to add a custom buff which adds +3 speed:
Buff buff = new Buff( id: "Example.ModId/ZoomZoom", displayName: "Zoom Zoom", // can optionally specify description text too iconTexture: this.Helper.ModContent.Load<Texture2D>("assets/zoom.png"), iconSheetIndex: 0, duration: 30_000, // 30 seconds effects: new BuffEffects() { Speed = { 10 } // shortcut for buff.Speed.Value = 10 } ); Game1.player.applyBuff(buff);
You can also implement your own custom effects in code by checking if the buff is active, like
Game1.player.hasBuff("Example.ModId/ZoomZoom")
.Custom audio
You can now add or edit music tracks or sound effects (called cues) by editing the Data/AudioChanges asset. New cues are added to the game's soundbank, so they can be used anywhere normal audio can be used (e.g. the Music map property).
Format
The Data/AudioChanges asset consists of a string → model lookup, where the key matches the ID, and the value is a model with the fields below.
Entries in this asset describe an override applied to the soundbank. The override is applied permanently for the current game session, even if the asset is edited to remove it. Overriding a cue will reset all values to the ones specified.
field effect ID A unique cue ID, used when playing the sound in-game. The ID should only contain alphanumeric/underscore/dot characters. For custom audio cues, this should be prefixed with your mod ID like Example.ModId_AudioName. FilePaths A list of file paths (not asset names) from which to load the audio. These can be absolute paths or relative to the game's Content folder. Each file can be .ogg or .wav. If you list multiple paths, a random one will be chosen each time it's played. Category The audio category, which determines which volume slider in the game options applies. This should be one of Default, Music, Sound, Ambient, or Footsteps (see a description of each category). Defaults to Default. StreamedVorbis Whether the audio should be streamed from disk when it's played, instead of being loaded into memory ahead of time. This is only possible for Ogg Vorbis (.ogg) files, which otherwise will be decompressed in-memory on load. Default false. This is a tradeoff between memory usage and performance, so you should consider which value is best for each audio cue:
value effect true Reduces memory usage when the audio cue isn't active, but increases performance impact when it's played. Playing the audio multiple times will multiply the memory and performance impact while they're active, since each play will stream a new instance. Recommended for longer audio cues (like music or ambient noise), or cues that are rarely used in a specific scenario (e.g. a sound that only plays once in an event). false Increases memory usage (since it's fully loaded into memory), but reduces performance impact when it's played. It can be played any number of times without affecting memory or performance (it'll just play the cached audio). Recommended for sound effects, or short audio cues that are played occasionally. Looped Whether the audio cue loops continuously until stopped. Default false. UseReverb Whether to apply a reverb effect to the audio. Default false. CustomFields The custom fields for this entry. Example
This content pack adds a new music cue to the game, and plays it when the player enters the bus stop:
{ "Format": "2.3.0", "Changes": [ // add music cue { "Action": "EditData", "Target": "Data/AudioChanges", "Entries": { "Example.ModId_Music": { "ID": "Example.ModId_Music", "Category": "Music", "FilePaths": [ "{{AbsoluteFilePath: assets/music.ogg}}" ], "StreamedVorbis": true, "Looped": true } } }, // add to bus stop { "Action": "EditMap", "Target": "Maps/BusStop", "MapProperties": { "Music": "Example.ModId_Music" } } ] }
Other changes
- The game no longer crashes when playing audio which doesn't exist. It now logs an error and returns a default quiet click sound instead. (If you use
try..catch
to check if an audio cue exists, you should checkGame1.soundbank.Exists(name)
instead.)
Custom data fields
Many data assets now have a CustomFields field. This is ignored by the game, but lets mods add their own data (e.g. to enable mod framework features).
For example, a content pack can add a crop with custom fields:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/Crops", "Entries": { "Example.Id_CucumberSeeds": { "Seasons": [ "summer" ], "DaysInPhase": [ 1, 2, 2, 2 ], "HarvestItemId": "Example.Id_Cucumber", "Texture": "{{InternalAssetKey: assets/crops.png}}", "SpriteIndex": 0, "CustomFields": { "Example.FrameworkMod/WetTexture": "{{InternalAssetKey: assets/crops-wet.png}}" } } } } ] }
And then a C# mod could handle the custom field if it's set:
if (Game1.currentLocation.IsRainingHere()) { CropData data = crop.GetData(); if (data != null && data.CustomFields.TryGet("Example.FrameworkMod/WetTexture", out string textureName)) { // do magic } }
See CustomFields in the docs for each asset type to see if it's supported. Besides the sections listed on this page, custom fields were also added to Data/AdditionalFarms, Data/AdditionalLanguages, Data/Movies, and Data/SpecialOrders.
Custom giant crops
You can now add/edit giant crops by editing the Data/GiantCrops data asset.
This consists of a string → model lookup, where...
- The key is a unique identifier for the giant crop. The ID should only contain alphanumeric/underscore/dot characters. For custom giant crops, this should be prefixed with your mod ID like Example.ModId_GiantCropName.
- The value is a model with the fields listed below.
field effect FromItemId The item ID (qualified or unqualified) for the harvest ID of the regular crop which can turn into this giant crop. For example, (O)254 is melon. Any number of giant crops can use the same FromItemId value. The first giant crop whose other fields match (if any) will spawn.
HarvestItems The items which can be dropped when you break the giant crop. If multiple items match, they'll all be dropped. 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 harvest items. If set to an item query which returns multiple items, one of them will be selected at random.
Chance (Optional) The probability that this entry is selected, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance). ForShavingEnchantment (Optional) Whether this item is only dropped for Shaving enchantment drops (true), only when the giant crop is broken (false), or both (null). Default both. ScaledMinStackWhenShaving
ScaledMaxStackWhenShaving(Optional) If set, the min/max stack size when this item is dropped due to the shaving enchantment, scaled to the tool's power level. This value is multiplied by the health deducted by the tool hit which triggered the enchantment. For example, an iridium axe which reduced the giant crop's health by 3 points will produce three times this value per hit.
If both fields are set, the stack size is randomized between them. If only one is set, it's applied as a limit after the generic fields. If neither is set, the generic MinStack/MaxStack fields are applied as usual without scaling.
Texture The asset name for the texture containing the giant crop's sprite. TexturePosition (Optional) The top-left pixel position of the sprite within the Texture, specified as a model with X and Y fields. Defaults to (0, 0). TileSize (Optional) The area in tiles occupied by the giant crop, specified as a model with X and Y fields. This affects both its sprite size (which should be 16 pixels per tile) and the grid of crops needed for it to grow. Note that giant crops are drawn with an extra tile's height. Defaults to (3, 3). Health (Optional) The health points that must be depleted to break the giant crop. The number of points depleted per axe chop depends on the axe power level. Default 3. Chance (Optional) The percentage chance that a given grid of crops will grow into the giant crop each night, as a value between 0 (never) and 1 (always). Default 0.01 (1%). Note that the chance is checked for each giant crop that applies. If three giant crops each have a 1% chance of spawning for the same crop, then there's a 3% chance that one of them will spawn.
Condition (Optional) A game state query which indicates whether this giant crop is available to spawn. Defaults to always true. CustomFields The custom fields for this entry. Custom movies
- See also: custom movie concessions.
You could already add/edit movies shown in the movie theater, but conflicts were likely since the poster & screen sprites for each movie had to be in the vanilla LooseSprites/Movies spritesheet.
Stardew Valley 1.6 adds a new movie field in Data/Movies to fix that:
field effect Texture (Optional) The asset name for the movie poster and screen images, or omit to use LooseSprites\Movies. This must be a spritesheet with one 490×128 pixel row per movie. A 13×19 area in the top-left corner of the row should contain the movie poster. With a 16-pixel offset from the left edge, there should be two rows of five 90×61 pixel movie screen images, with a six-pixel gap between each image. (The movie doesn't need to use all of the image slots.)
The existing SpriteIndex field is now an index within that texture.
For example, this content pack adds a new 'Pufferchick II' movie:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/Movies", "Entries": { "Example.ModId_PufferchickII": { "Id": "Example.ModId_PufferchickII", // must specify ID again when creating a new entry "Title": "Pufferchick II", // display text should usually use {{i18n}} for translations in actual usage "Description": "A sequel to the breakthrough adventure anime Pufferchick. The world is saved; what happens next?", "Tags": [ "family", "adventure" ], "Texture": "{{InternalAssetKey: assets/movie.png}}", // an image in your content pack "SheetIndex": 0, "Scenes": [ ... ] } } } ] }
Custom wedding event
The wedding event can now be changed by editing the Data\Weddings data asset, which consists of a data model with two relevant fields (listed below).
field effect EventScript The event scripts which play the wedding. The game will use the script for the spouse NPC/player if it exists, otherwise it'll use the default script. This consists of a string → string dictionary, where...
- The key is an NPC internal name (like Abigail), unique player ID, or default for the default script (which handles marrying either an NPC or player);
- The value is a tokenizable strings for the event script to play.
The event scripts also have access to three extra tokens:
token effect [SetupContextualWeddingAttendees] The concatenated Setup values for each of the Attendees present in the wedding. [ContextualWeddingCelebrations] The concatenated Celebration values for each of the Attendees present in the wedding. [SpouseActor] The actor ID for the NPC or other player being married (like Abigail for an NPC or farmer2 for a player). This can be used in event commands like faceDirection [SpouseActor] 1
.(You can also use spouse as an actor ID, but that will only work when marrying an NPC.)
Attendees The other NPCs which should attend the wedding (unless they're the spouse). This consists of a string → model lookup, where the key is the internal NPC name, and the value is a model with these fields: field effect ID The internal NPC name. Setup The NPC's tile position and facing direction when they attend. This is equivalent to field index 2 in the event basic data. Celebration (Optional) The event script to run during the celebration, like faceDirection Pierre 3 true which makes Pierre turn to face left. This can contain any number of script commands. Condition (Optional) A game state query which indicates whether the NPC should attend. Defaults to true. Game state queries
A game state query is a vanilla way to specify conditions for some content like shop data, inspired by Content Patcher's conditions. A query consists of a comma-delimited list of conditions in the form
<type>
[arguments]
. The type can be prefixed with!
to negate it. The query is true if it's null/blank, or if every listed condition exists and is true. For example,!SEASON Spring, WEATHER Here Sun
is true on sunny non-spring days.⚠ Game state queries are partly case-sensitive. While some values are case-insensitive (e.g. both
SEASON Spring
andSEASON spring
will work), this isn't consistent. Using the exact capitalization is recommended to avoid issues.Argument format
Game state queries take space-delimited arguments. For example,
BUILDINGS_CONSTRUCTED Here Cabins
has two arguments:Here
andCabins
.You can add quotes to keep spaces within an argument. For example,
BUILDINGS_CONSTRUCTED Here "Junimo Hut"
passesJunimo Hut
as one argument. You can escape inner quotes with backslashes likeANY "BUILDINGS_CONSTRUCTED Here \"Junimo Hut\""
. Remember that quotes and backslashes inside JSON strings need to be escaped too, like"Condition": "BUILDINGS_CONSTRUCTED Here \"Junimo Hut\""
.Conditions
- Meta
-
Condition effect ANY <query>
+Get whether at least one of the listed game state queries match, where each argument is a query. For example, ANY "SEASON Winter" "SEASON Spring, DAY_OF_WEEK Friday"
is true if (a) it's winter or (b) it's a spring Friday. You can list any number of queries to check. - Date & time
-
Condition effect DAY_OF_MONTH <day>
+The day of month. This can be an integer between 1 and 28, or even/odd to match on any even/odd day. You can specify multiple values to match any of them. DAY_OF_WEEK <day>
+The day of week. This can be an integer between 0 (Sunday) and 6 (Saturday), three-letter English name (like Fri), or full English name (like Friday). You can specify multiple values to match any of them (like DAY_OF_WEEK Monday Tuesday for Monday or Tuesday). DAYS_PLAYED <min>
[max]
Whether <min>
to[max]
(default unlimited) days have been played in the current save (including the current one). This always increments in sync with the date in the base game, but when mods change the in-game date, they may or may not update this value.IS_FESTIVAL_DAY [day offset]
Whether there's a festival today, with an optional [day offset]
(e.g. 1 for tomorrow).IS_PASSIVE_FESTIVAL_OPEN <id>
Whether a passive festival with the given ID is active today, and the current time is within its opening hours. IS_PASSIVE_FESTIVAL_TODAY <id>
Whether a passive festival with the given ID is active today. SEASON <season>
+The season (one of spring, summer, fall, or winter). You can specify multiple values to match any of them (like SEASON spring summer for spring or summer). SEASON_DAY [ <season>
<day>
]+The season (in the same format as SEASON) and day (an integer between 1 and 28). You can specify multiple values to match any of them (like SEASON_DAY fall 15 winter 20 for fall 15 or winter 20). TIME <min>
[max]
Whether the current time is between <min>
and[max]
(default unlimited) inclusively, specified in 26-hour time.YEAR <min>
[max]
Whether the current year is between <min>
and[max]
(default unlimited) inclusively. - World
-
Condition effect BUILDINGS_CONSTRUCTED <locations>
[building type]
[min]
[max]
[count unbuilt]
Whether the number of matching buildings is within a range. For example:
BUILDINGS_CONSTRUCTED Here
checks if any buildings were constructed in the player's current location.BUILDINGS_CONSTRUCTED Target Cabin
checks if there's at least one cabin in the target location.BUILDINGS_CONSTRUCTED All "Junimo Hut" 3 5
checks if there's between 3 and 5 Junimo huts (inclusively) anywhere in the world.
Arguments:
<locations>
: a target location, or All to count buildings in all locations.[building type]
: the building ID in Data/Buildings to count, or All to count all building types. Note that All includes default buildings like the farmhouse.[min]
/[max]
: the minimum (default 1) and maximum (default unlimited) count to require.[count unbuilt]
: whether to count buildings that haven't been fully constructed yet.
CAN_BUILD_CABIN Whether players can build more cabins (i.e. they haven't reached the maximum number of player slots yet). CAN_BUILD_FOR_CABINS <building ID>
Whether there are fewer of the given building constructed than there are cabins. FARM_CAVE <type>
The current farm cave (one of Bats, Mushrooms, or None). FARM_NAME <name>
The name of the farm. FARM_TYPE <type>
The farm type. The <type>
can be one of...- a numeric ID for a vanilla farm type: 1 (standard), 2 (riverland), 3 (forest), 4 (hilltop), 5 (combat), 6 (four corners), or 7 (beach);
- a readable key for a vanilla farm type: Standard, Beach, Forest, FourCorners, Hilltop, Riverland, or Wilderness;
- or the ID for a custom farm type.
FOUND_ALL_LOST_BOOKS Whether all the Lost Books for the museum have been found. IS_COMMUNITY_CENTER_COMPLETE Whether the community center has been repaired. IS_CUSTOM_FARM_TYPE Whether the farm type is a custom one created by a mod. (This returns false for mods which edit/replace a vanilla farm type.) IS_HOST Whether the current player is the main/host player. IS_ISLAND_NORTH_BRIDGE_FIXED Whether the North Ginger Island bridge to the dig site has been repaired. IS_JOJA_MART_COMPLETE Whether the Joja warehouse has been built. IS_MULTIPLAYER Whether the game is currently in multiplayer mode (regardless of whether there's multiple players connected). IS_VISITING_ISLAND <name>
Whether the named NPC is visiting Ginger Island today. LOCATION_ACCESSIBLE <name>
Whether the given location is accessible. For vanilla locations, this is relevant to CommunityCenter, JojaMart, or Railroad; any other location will return true unless a mod customizes the query. LOCATION_CONTEXT <location>
The location context name for the given location. LOCATION_IS_INDOORS <location>
LOCATION_IS_OUTDOORS<location>
LOCATION_IS_MINES<location>
LOCATION_IS_SKULL_CAVE<location>
Whether the given location is indoors, outdoors, in the mines, or in the Skull Cavern. LOCATION_SEASON <location>
[<season>
]+Whether the given location is in one of the given seasons (which can be spring, summer, fall, or winter). This accounts for the SeasonOverride field in the location's context data. For example, this is valid in spring or summer:
LOCATION_SEASON Here spring summer
.MUSEUM_DONATIONS <min count>
[max count]
[object type]
+Whether all players have donated a total of <min count>
to[max count]
(default unlimited) inclusively to the museum. This can optionally be filtered by the object type field, like MUSEUM_DONATIONS 40 Arch Minerals to require at least 40 artifacts and minerals combined. You can omit the max count and still specify a filter.WEATHER <location>
<weather>
The weather ID in the given location. The weather can be one of Festival, Rain, Snow, Storm, Sun, Wind, or a custom weather ID. WORLD_STATE_FIELD <name>
<value>
Whether a property on Game1.netWorldState has the given value. If the property is numeric, this is the minimum value. Some useful values not covered by their own query: name effect GoldenCoconutCracked Whether the player has cracked open any Golden Coconuts (true or false). GoldenWalnutsFound
GoldenWalnutsThe total number of Golden Walnuts found or held by any player. To check how many one player currently holds, see the PLAYER_HAS_ITEM query. IsGoblinRemoved Whether the Henchman has been removed, so the player can access Witch's Hut (true or false). IsSubmarineLocked Whether the Night Market submarine is currently in use by a player (true or false). LostBooksFound The total number of Lost Books found or held by any player. MinesDifficulty
SkullCavesDifficultyThe current Shrine of Challenge difficulty level for the mine or Skull Cavern (a numeric value, where 0 is the default level when the shrine is deactivated). MiniShippingBinsObtained The number of times the player has obtained a Mini-Shipping Bin. ParrotPlatformsUnlocked Whether the player has unlocked Ginger Island parrot platforms, regardless of whether they've completed them (true or false). ServerPrivacy The multiplayer connection privacy mode (InviteOnly or FriendsOnly). ShuffleMineChests The value of the 'mine rewards' game option (Default or Remixed). WeatherForTomorrow The weather ID for tomorrow in the main valley area. VisitsUntilY1Guarantee The number of times the Traveling Cart will visit before Red Cabbage is guaranteed to drop. For example, the Traveling Cart shop uses a
WORLD_STATE_FIELD VisitsUntilY1Guarantee 0
condition to check if it should guarantee a Red Cabbage item.WORLD_STATE_FIELD <name>
<min>
<max>
For numeric properties only, whether a property on Game1.netWorldState has a value between <min>
and<max>
. If<max>
is omitted or the properties isn't numeric, the previous form is used. See the previous entry for a list of useful properties.WORLD_STATE_ID <id>
Whether any world state flag with the given <id>
is set. - Player info & progress
-
Condition effect MINE_LOWEST_LEVEL_REACHED <min>
[max]
Whether any player has reached a level between <min>
and<max>
(default unlimited) inclusively in the mines.PLAYER_COMBAT_LEVEL <player>
<min>
[max]
PLAYER_FARMING_LEVEL<player>
<min>
[max]
PLAYER_FISHING_LEVEL<player>
<min>
[max]
PLAYER_FORAGING_LEVEL<player>
<min>
[max]
PLAYER_LUCK_LEVEL<player>
<min>
[max]
PLAYER_MINING_LEVEL<player>
<min>
[max]
Whether the specified player(s) have a skill level between <min>
and<max>
(default unlimited) inclusively, including the effects of buffs which raise them.PLAYER_CURRENT_MONEY <player>
<min>
[max]
Whether the specified player(s) have between <min>
and[max]
(default unlimited) gold inclusively.PLAYER_FARMHOUSE_UPGRADE <player>
<min>
[max]
Whether the specified player(s) have upgraded their farmhouse or cabin to a level between <min>
and[max]
(default unlimited) inclusively. See possible levels.PLAYER_GENDER <player>
<gender>
Whether the specified player(s) are Male or Female. PLAYER_HAS_ACHIEVEMENT <player>
<achievement id>
Whether the specified player(s) have unlocked a specific achievement ID. The valid IDs are listed in Data/Achievements, plus a few Steam achievement IDs that aren't listed. PLAYER_HAS_ALL_ACHIEVEMENTS <player>
Whether the specified player(s) have unlocked every achievement listed in Data/Achievements. This doesn't count the extra Steam achievement IDs that aren't listed in that file. PLAYER_HAS_CAUGHT_FISH <player>
<id>
Whether the specified player(s) have caught at least one fish with the given ID. PLAYER_HAS_CONVERSATION_TOPIC <player>
<id>
Whether the specified player(s) have a conversation topic with the ID <id>
active.PLAYER_HAS_CRAFTING_RECIPE <player>
<recipe name>
PLAYER_HAS_COOKING_RECIPE<player>
<recipe name>
Whether the specified player(s) know the crafting/cooking recipe identified by its internal name (spaces allowed). For example, PLAYER_HAS_CRAFTING_RECIPE Current Field Snack
.PLAYER_HAS_DIALOGUE_ANSWER <player>
<id>
Whether the specified player(s) have chosen the given dialogue answer in a previous dialogue. PLAYER_HAS_FLAG <player>
<id>
Whether the specified player(s) have the given mail flag set (with spaces allowed in the <id>
).PLAYER_HAS_ITEM <player>
<item>
[min]
[max]
Whether the specified player(s) have between [min]
and[max]
(default unlimited) matching items in their inventory, inclusively. The<item>
can be 858 or (O)858 (Qi Gems), 73 or (O)73 (Walnuts), or the qualified or unqualified item ID.PLAYER_HAS_PROFESSION <player>
<profession id>
Whether the specified player(s) have the given profession ID. PLAYER_HAS_READ_LETTER <player>
<id>
Whether the specified player(s) have read a letter, where <id>
is the internal mail ID (spaces allowed). For example,PLAYER_HAS_READ_LETTER Any Visited_Island
.PLAYER_HAS_SECRET_NOTE <player>
<id>
Whether the specified player(s) have read a secret note, where <id>
is the secret note's integer ID.PLAYER_HAS_SEEN_EVENT <player>
<id>
Whether the specified player(s) have seen the event with given <id>
.PLAYER_HAS_TOWN_KEY <player>
Whether the specified player(s) have the town key. PLAYER_HAS_TRASH_CAN_LEVEL <player>
<min>
[max]
Whether the specified player(s) have a trash can upgrade level between <min>
and[max]
(default unlimited) inclusively. The<level>
can be 0 (base), 1 (copper), 2 (steel), 3 (gold), or 4 (iridium).PLAYER_LOCATION_CONTEXT <player>
<location context>
Whether the specified player(s) are in the given location context. PLAYER_LOCATION_NAME <player>
<location name>
PLAYER_LOCATION_UNIQUE_NAME<player>
<location name>
Whether the specified player(s) are in the given location, using the name or unique instanced name (you can see both names in-game using the Debug Mode mod). The <location name>
value doesn't recognize target location keywords like Here.PLAYER_MOD_DATA <player>
<key>
<value>
Whether the specified player(s) have a player.modData entry added by a mod with the given <key>
and<value>
.PLAYER_MONEY_EARNED <player>
<min>
[max]
Whether the specified player(s) have earned between <min>
and[max]
(default unlimited) gold inclusively.PLAYER_SHIPPED_BASIC_ITEM <player>
<item ID>
[min count]
<max count>
Whether the specified player(s) have shipped the given item between [min count]
(default 1) and[max count]
(default unlimited) times inclusively. This only works for the items tracked by the game for shipping stats (shown in the shipping collections menu).PLAYER_SPECIAL_ORDER_ACTIVE <player>
<order id>
Whether the specified player(s) have the given special order active. PLAYER_SPECIAL_ORDER_RULE_ACTIVE <player>
<rule id>
Whether the specified player(s) have a special rule active for a special order. Some vanilla rules are... rule ID effect DROP_QI_BEANS The player can find Qi Beans for the Qi's Crop order. LEGENDARY_FAMILY The player catch the new legendary fish for the Extended Family order. MINE_HARD
SC_HARDRaises the difficulty level of the mines or Skull Cavern. SC_NO_FOOD The player can't eat food in the Skull Cavern. PLAYER_STAT <player>
<stat name>
<min value>
[max value]
Whether a stat counter for the specified player(s) has a value between <min value>
and[max value]
(default unlimited) inclusively. The available stat names are...- averageBedtime;
- beachFarmSpawns;
- beveragesMade;
- boatRidesToIsland;
- bouldersCracked;
- caveCarrotsFound;
- cheeseMade;
- chickenEggsLayed;
- childrenTurnedToDoves;
- coalFound;
- coinsFound;
- copperFound;
- cowMilkProduced;
- cropsShipped;
- daysPlayed;
- diamondsFound;
- dirtHoed;
- duckEggsLayed;
- exMemoriesWiped;
- fishCaught;
- geodesCracked;
- giftsGiven;
- goatCheeseMade;
- goatMilkProduced;
- goldFound;
- goodFriends;
- hardModeMonstersKilled;
- individualMoneyEarned;
- iridiumFound;
- ironFound;
- itemsCooked;
- itemsCrafted;
- itemsForaged;
- itemsShipped;
- monstersKilled;
- mysticStonesCrushed;
- notesFound;
- otherPreciousGemsFound;
- piecesOfTrashRecycled;
- preservesMade;
- prismaticShardsFound;
- questsCompleted;
- rabbitWoolProduced;
- rocksCrushed;
- seedsSown;
- sheepWoolProduced;
- slimesKilled;
- starLevelCropsShipped;
- stepsTaken;
- sticksChopped;
- stoneGathered;
- stumpsChopped;
- timesEnchanted;
- timesFished;
- timesUnconscious;
- totalMoneyGifted;
- trashCansChecked;
- trufflesFound;
- walnutsFound;
- weedsEliminated.
- Player relationships
-
Condition effect PLAYER_HAS_CHILDREN <player>
[min]
[max]
Whether the specified player(s) have a number of children between <min>
(default 1) and[max]
(default unlimited) inclusively.PLAYER_HAS_PET <player>
Whether the specified player(s) have a pet. PLAYER_HEARTS <player>
<npc>
<min hearts>
[max hearts]
Whether the specified player(s) have a friend with a friendship level between <min hearts>
and[max hearts]
(default unlimited) inclusively. The<npc>
can be an NPC's internal name, Any (check every NPC), or AnyDateable (check every romanceable NPC).PLAYER_HAS_MET <player>
<npc>
Whether the specified player(s) have talked to an NPC at least once. The <npc>
is an NPC's internal name.PLAYER_IS_DATING <player>
<npc>
PLAYER_IS_ENGAGED<player>
<target>
PLAYER_IS_MARRIED<player>
<target>
PLAYER_IS_DIVORCED<player>
<npc>
Whether the specified player(s) have this relationship status with an NPC. The player is dating after giving the NPC a bouquet, and engaged after giving a Mermaid's Pendant but before the marriage. The <npc>
can be an NPC's internal name, or Any (check every romanceable NPC).PLAYER_IS_ROOMMATE <player>
<target>
Whether the specified player(s) have a roommate. The <target>
can be an NPC's internal name, Any (with any NPC), or Player (always false).PLAYER_PREFERRED_PET <player>
<pet>
Whether the preferred pet for the specified player(s) is Cat, Dog, or a specified custom pet type. - Randomization
-
Condition effect RANDOM <chance>
[@addDailyLuck]
A random probability check which is re-rolled each time it's called. For example, RANDOM 0.4
is true 40% of the time.If the exact text @addDailyLuck is specified, the current player's daily luck is added to the probability.
SYNCED_CHOICE <interval>
<key>
<min>
<max>
<choices>
+Choose a random integer between <min>
and<max>
inclusively, and check whether it matches one of the<choices>
. The result will be identical for all queries with the same<key>
value during the given<interval>
(one of tick, day, season, or year), including between players in multiplayer mode.For example, SYNCED_CHOICE day example_key 1 5 1 2 chooses a random value between 1 and 5, and checks if it's either 1 or 2.
This is mainly useful in cases where you need to pick between a number of discrete cases. For regular probability checks, see SYNCED_RANDOM instead.
SYNCED_RANDOM <interval>
<key>
<chance>
[@addDailyLuck]
A random probability check. The result will be identical for all queries with the same <key>
value during the given<interval>
(one of tick, day, season, or year), including between players in multiplayer mode.For example, SYNCED_RANDOM day cart_rare_seed 0.4 has a 40% chance to be true the first time it's called that day, and will always be the same value if called again with the same key on the same day.
If the exact text @addDailyLuck is specified, the current player's daily luck is added to the probability.
SYNCED_SUMMER_RAIN_RANDOM <base chance>
<day multiplier>
A specialized variant of SYNCED_DAY_RANDOM used to calculate the chance of rain in summer, which increases with the day number. - For items only
-
These queries apply in cases where there's an item (e.g. machine recipes, shops, etc); they'll return false if not applicable. They take a
<type>
argument which can be Input (the machine input item) or Target (the machine output, tree fruit, shop item, etc).Condition effect ITEM_HAS_TAG <target>
<tags>
Whether the item has all of the given space-delimited tags. For example, ITEM_HAS_TAG Target bone_item marine_item
will only match items with both tags.ITEM_ID <target>
<item ID>
Whether the item has the given qualified or unqualified item ID. The item ID is qualified before checking, so 128 will match pufferfish ((O)128) but not mushroom boxes ((BC)128). ITEM_QUALITY <target>
<min>
<max>
Whether the item's quality is between <min>
and<max>
(default unlimited) inclusively. The possible values are 0 (normal), 1 (silver), 2 (gold), or 4 (iridium).ITEM_STACK <target>
<min>
<max>
Whether the item stack size is between <min>
and<max>
(default unlimited) inclusively. Note that this only applies to the target item, it doesn't include other stacks in the inventory.ITEM_TYPE <target>
<type>
Whether the item's type definition ID matches the given value. For example, ITEM_TYPE Target (BC) matches bigcraftables. - Immutable
-
Condition effect TRUE A condition which always matches. FALSE A condition which never matches.
Target location
Some conditions have a
<location>
argument. This can be one of...value result Here The location containing the current player (regardless of the target player). Target The location containing the in-game entity being edited (e.g. the machine for Data/Machines or fruit tree for Data/FruitTrees). If the asset being edited isn't tied to a location, this is the location of the target player (if set), else equivalent to Here.
any other The location ID (i.e. internal name) for the location to check. Target player
Some conditions have a
<player>
argument. This can be one of...value result Any At least one player must match the condition, regardless of whether they're online. All Every player must match the condition, regardless of whether they're online. Current The local player. Host The main player. Target This value depends on the context: context effect Data/LocationContexts For the PassOutLocations field only, the player whose pass-out location to get. Data/Weddings For the Attendees field only, the attendee player (if the attendee is a player). Data/WildTrees For the AdditionalChopDrops field only, the last player who chopped the tree. custom queries C# mods may specify a target_farmer parameter when calling GameStateQuery.CheckConditions. any other Equivalent to Current. any other The unique multiplayer ID for the player to check. Using queries elsewhere
C# code can use the GameStateQuery class to work with queries, like
GameStateQuery.CheckConditions(query)
.You can also use game state queries in event preconditions using the new G condition flag, like
some_event_id/G !SEASON Spring, WEATHER Here Sun
.Extensibility
C# mods can check if a query exists using
GameStateQuery.Exists("Example.ModId_ConditionName")
, and define custom conditions usingGameStateQuery.Register("Example.ModId_ConditionName", handleQueryMethod)
. To avoid conflicts, prefixing custom condition names with your mod ID is strongly recommended.Item queries
Item queries choose one or more items dynamically, instead of specifying a single item ID. These are used in various places like machine data and shop data.
Available queries
The supported item queries are:
query effect ALL_ITEMS [type ID]
Every item provided by the item data definitions. If [type ID]
is set to an item type identifier (like (O) for object), only returns items from the matching item data definition.DISH_OF_THE_DAY The Saloon's dish of the day. FLAVORED_ITEM <type>
<ingredient ID>
[ingredient flavor ID]
A flavored item like Apple Wine. The <type>
can be one of AgedRoe, Honey, Jelly, Juice, Pickle, Roe, or Wine. The<ingredient ID>
is the qualified or unqualified item ID which provides the flavor (like Apple in Apple Wine). For Honey, you can set the<flavor ID>
to -1 for Wild Honey.For aged roe only, the
[ingredient flavor ID]
is the flavor of the<ingredient ID>
. For example, FLAVORED_ITEM AgedRoe (O)812 128 creates Aged Pufferfish Roe (812 is roe and 128 is pufferfish).ITEMS_SOLD_BY_PLAYER <shop location>
Random items the player has recently sold to the <shop location>
, which can be one of SeedShop (Pierre's store) or FishShop (Willy's fish shop).LOCATION_FISH <location>
<bobber tile>
<depth>
A random item that can be found by fishing in the given location. The <location>
should be the internal name of the location,<bobber tile>
is the position of the fishing rod's bobber in the water (in the form<x>
<y>
), and<depth>
is the bobber's distance from the nearest shore measured in tiles (where 0 is directly adjacent to the shore).Careful: since the target location might use LOCATION_FISH queries in its list, it's easy to cause a circular reference by mistake (e.g. location A gets fish from B, which gets fish from A). If this happens, the game will log an error and return no item.
LOST_BOOK_OR_ITEM [alternate query]
Returns a lost book if the player hasn't found them all yet, else the result of the [alternate query]
if specified, else nothing.For example,
LOST_BOOK_OR_ITEM (O)770
returns mixed seeds if the player found every book already.RANDOM_ARTIFACT_FOR_DIG_SPOT A random item which is defined in Data/Objects with the Arch (artifact) type, and whose spawn rules in the Miscellaneous field match the current location and whose random probability passes. This is mainly used by artifact spots. RANDOM_BASE_SEASON_ITEM A random seasonal vanilla item which can be found by searching garbage cans, breaking containers in the mines, etc. RANDOM_ITEMS <type definition ID>
[options]
Random items from the given type definition ID, with any combination of the following criteria and options (in any order, all optional): format item criteria search criteria @has_category [category]
Must have one of the given object categories (space-delimited), or any valid category if none specified. Can be negated with @!has_category. @has_id <id>
+Must have one of the given unqualified item IDs. Can be negated with @!has_id. @has_id_in_base_range <min>
<max>
Must have a numeric ID between the <min>
and<max>
values (inclusive). Can be negated with @!has_id_in_base_range .@has_id_prefix <prefix>
+Must have an unqualified item ID starting with one of the given prefixes. For example, @has_id_prefix ExampleAuthor_ExampleMod_ for a mod's items. Can be negated with @!has_id_prefix. @has_object_type [type]
+Must have one of the given object ty pes (space-delimited), or any valid type if none specified. Can be negated with @!has_object_type. options @allow_missing_price Allow items with a base sell price of 0 or lower. If omitted, those items are skipped. @count <count>
The number of random items to return. Default 1. @require_explicit_category Whether to ignore items with category 0 in Data/Objects. These are often (but not always) special items like Secret Note or unimplemented items like Lumber. For example, you can sell a random wallpaper for
200g in Data/Shops:
{ "ItemId": "RANDOM_ITEMS (WP)", "Price": 200 }
Or a random house plant:
{ "ItemId": "RANDOM_ITEMS (F) @has_id_in_base_range 1376 1390" }
Or a random custom item added by a mod by its item ID prefix:
{ "ItemId": "RANDOM_ITEMS (O) @has_id_prefix AuthorName_ModName_" }
Or 10 random objects with any category except -13 or -14:
{ "ItemId": "RANDOM_ITEMS (O) @has_category @!has_category -13 -14 @count 10" }
SECRET_NOTE_OR_ITEM [alternate query]
Returns a secret note (or journal scrap on the island) if the player hasn't found them all yet, else the result of the [alternate query]
if specified, else nothing.For example,
SECRET_NOTE_OR_ITEM (O)390
returns clay if the player found every secret note already.SHOP_TOWN_KEY The special town key item. This is only valid in shops. TOOL_UPGRADES [tool ID]
The tool upgrades listed in Data/Shops whose conditions match the player's inventory (i.e. the same rules as Clint's tool upgrade shop). If [tool ID]
is specified, only upgrades which consume that tool ID are shown.Item spawn fields
Several data assets (like machines and shops) let you configure items to create. For consistency, these all share a set of common fields (internally represented by ISpawnItemData, and GenericSpawnItemData or GenericSpawnItemDataWithCondition):
field effect ID A unique identifier for this entry (not the item itself) within the current list. The ID should only contain alphanumeric/underscore/dot characters. For custom items, this should be prefixed with your mod ID like Example.ModId_Parsnips. This is semi-optional — if omitted, it'll be auto-generated from the ItemId, RandomItemId, and IsRecipe fields. However multiple entries with the same ID may cause unintended behavior (e.g. shop items reducing each others' stock limits), so it's often a good idea to set a globally unique ID instead.
ItemId One of: - the qualified or unqualified item ID (like (O)128 for a pufferfish);
- or an item query to dynamically choose one or more items.
RandomItemId (Optional) A list of item IDs to randomly choose from, using the same format as ItemId (including item queries). If set, ItemId is optional and ignored. Each entry in the list has an equal probability of being chosen. For example: // wood, stone, or pizza "RandomItemId": [ "(O)388", "(O)390", "(O)206" ]
Condition (Optional) A game state query which indicates whether this entry should be applied. Defaults to always true. Note: not supported for weapon projectiles.
IsRecipe (Optional) Whether to get the crafting/cooking recipe for the item, instead of the item itself. Default false. Quality (Optional) The quality of the item to find. One of 0 (normal), 1 (silver), 2 (gold), or 4 (iridium). Invalid values will snap to the closest valid one (e.g. 7 will become iridium). Default -1, which keeps the value set by the item query (usually 0). MinStack (Optional) The item's minimum and default stack size. Default -1, which keeps the value set by the item query (usually 1). MaxStack (Optional) If set to a value higher than MinStack, the stack is set to a random value between them (inclusively). Default -1. ObjectDisplayName (Optional) For objects only, a tokenizable string for the item's display name. Defaults to the item's display name in Data/Objects. This can optionally contain %DISPLAY_NAME
(the item's default display name) and%PRESERVED_DISPLAY_NAME
(the preserved item's display name if applicable, e.g. if set via PreserveId in machine data).Careful: text in this field will be saved permanently in the object's info and won't be updated when the player changes language or the content pack changes. That includes Content Patcher translations (like
%DISPLAY_NAME {{i18n: wine}}
), which will save the translated text for the current language. Instead, add the text to a strings asset like Strings/Objects and then use the [LocalizedText] token.For example, here's how you'd create flavored oils with Content Patcher: - Add the display name to your i18n/default.json file (with {0} where you want the flavor name):
{ "flavored-oil": "{0} Oil" }
- Add the text to a strings asset visible to the game:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Strings/Objects", "Entries": { "Example.ModId_Oil": "{{i18n: flavored-oil}}" } } }
- Use the [LocalizedText] token to get your translation, and pass in the flavor as an argument:
"ObjectDisplayName": "[LocalizedText Strings/Objects:Example.ModId_Oil %PRESERVED_DISPLAY_NAME]",
Now when the player changes language, the object will automatically get the new translation from Strings/Object.
ToolUpgradeLevel (Optional) For tools only, the initial upgrade level for the tool when created (like Copper vs Gold Axe, or Training Rod vs Iridium Rod). Default -1, which keeps the value set by the item query (usually 0). QualityModifiers
StackModifiers(Optional) Quantity modifiers applied to the Quality or Stack value. Default none. The quality modifiers operate on the numeric quality values (i.e. 0 = normal, 1 = silver, 2 = gold, and 4 = iridium). For example, silver × 2 is gold.
QualityModifierMode
StackModifierMode(Optional) quantity modifier modes which indicate what to do if multiple modifiers in the QualityModifiers or StackModifiers field apply at the same time. Default Stack. Color fields
1.6 adds a standardized color format for data fields in assets like Data/WildTrees:
"DebrisColor": "White"
This supports colors in any of these formats:
format example A Color property name. ForestGreen A hexadecimal color code. The optional alpha is a value between 00 (transparent) and FF (opaque). #228B22
#228B22FFAn 8-bit RGB color code. The optional alpha is a value between 0 (transparent) and 255 (opaque). 34 139 34
34 139 34 255C# mods can parse a color like
Utility.StringToColor("White")
.More modData fields
The modData fields are dictionaries of arbitrary string values which are synchronized in multiplayer and persisted in the save file, so mods can store custom data about the instances. The game already has the field for buildings, characters (including NPCs and players), items, locations, and terrain features.
Stardew Valley 1.6 adds modData fields to the Projectile and Quest types too, to support custom projectile/quest mods.
Quantity modifiers
Quantity modifiers apply dynamic changes to a numeric field in a data asset like Data/Shops or Data/Machines. For example, you can multiply a shop item's price or increase a machine output's quality. You can specify any number of modifiers for the same field.
Modifier format
These consist of a list of models with these fields:
field effect Id An ID for this modifier. This only needs to be unique within the current modifier list. For a custom entry, you should use a unique ID which includes your mod ID like ExampleMod.Id_ModifierName. Modification The type of change to apply. The possible values are Add, Subtract, Multiply, Divide, and Set. Amount (Optional if RandomAmount specified) The operand applied to the target value (e.g. the multiplier if used with Multiply). RandomAmount (Optional) A list of possible amounts to randomly choose from. If set, Amount is optional and ignored. Each entry in the list has an equal probability of being chosen, and the choice is persisted for the current day. For example: "RandomAmount": [ 1, 2, 3.5, 4 ]
Condition (Optional) A game state query which indicates whether this change should be applied. Defaults to always true. Modifier mode
Quality modifier fields are often accompanied by a mode field (like PriceModifiers and PriceModifierMode), which indicate what to do when multiple modifiers apply to the same value. Available modes:
value effect Stack Apply each modifier to the result of the previous one. For example, two modifiers which double a value will quadruple it. Minimum Apply the modifier which results in the lowest value. Maximum Apply the modifier which results in the highest value. Examples
For example, this will double the price of a shop item in Data/Shops:
"PriceModifiers": [ { "Modification": "Multiply", "Amount": 2.0 } ]
This will set the price to a random value between 100–1000, or 3–5 times the item's normal sell price, whichever is higher (like the Traveling Cart):
"PriceModifierMode": "Maximum", "PriceModifiers": [ { "Modification": "Set", "RandomAmount": [ 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 ] }, { "Modification": "Multiply", "RandomAmount": [ 3, 4, 5 ] } ]
Tokenizable string format
Stardew Valley 1.6 adds support for literal strings that contain tokens. These are only usable in specific fields (their docs will say 'tokenizable string' with a link to this section).
Literal text
Previously you often needed to load text from a string key in data assets. With this new format, you can use the literal text directly in the asset instead (including Content Patcher tokens):
// before "Dialogue": "Strings\\StringsFromCSFiles:ShopMenu.cs.11488", // after: literal text supported "Dialogue": "Welcome to Pierre's!", // after: literal text with Content Patcher tokens "Dialogue": "Welcome to Pierre's, {{PlayerName}}! {{i18n: translatable-text}}",
Tokens
You can inject tokens using square brackets. For example,
"[LocalizedText Strings\StringsFromCSFiles:ShopMenu.cs.11488] This is raw text"
will show something like "Welcome to Pierre's! This is raw text". Token names are not case-sensitive.Here are the supported tokens:
token format output [ArticleFor <word>
]The grammatical article (a or an) for the given word when playing in English, else blank. For example, [ArticleFor apple] apple
will output an apple.[CharacterName <name>
]The translated display name for an NPC, given their internal name. [DayOfMonth] The numeric day of month, like 5 on spring 5. [EscapedText]
[EscapedText<text>
]Marks a snippet of text as a single argument, so it can be safely passed into another token's space-delimited arguments even if it's empty or contains spaces. For example, the SpouseFarmerText expects two arguments separated by spaces. This passes an empty string for the first one, and text containing spaces for the second:
[SpouseFarmerText [EscapedText] [EscapedText spouse 28 63 2]]
[FarmerUniqueID] The target player's unique internal multiplayer ID [FarmName] The farm name for the current save (without the injected "Farm" text). [GenderedText <male text>
<female text>
Depending on the target player's gender, show either the male text or female text. If the text contains spaces, you'll need to escape them using EscapedText. [LocalizedText <string key>
]
[LocalizedText<string key>
<token values>
+]Translation text loaded from the given string key. If the translation has placeholder tokens like {0}, you can add the values after the string key. [LocationName <location ID>
]The translated display name for a location given its ID in Data/Locations. [PositiveAdjective] A random adjective from the Strings\Lexicon data asset's RandomPositiveAdjective_PlaceOrEvent entry. [Season] The current season name, like spring. [SpouseFarmerText <spouse is farmer text>
<spouse is NPC text>
Show a different text depending on whether the target player's spouse is a player or NPC. If the text contains spaces, you'll need to escape them using EscapedText. [SpouseGenderedText <male text>
<female text>
]Equivalent to GenderedText, but based on the gender of the player's NPC or player spouse instead. [SuggestedItem [interval]
[sync key]
](For shops only.) The name of a random item currently available in the shop stock. The result will be identical for all queries with the same
[sync key]
during the given[interval]
(one of tick, day, season, year), including between players in multiplayer mode. If omitted, they default to day and the shop ID respectively.When passing an input argument for tokens like ArticleFor, the input can contain its own nested tokens. For example,
"[ArticleFor [SuggestedItem]] [SuggestedItem]"
would output something like an Apple.If you're using Content Patcher, you can use its tokens anywhere in the string (including within square brackets); they'll be expanded before the game parses the string. For example,
"{{Spouse}} would love [ArticleFor [SuggestedItem]] [SuggestedItem]!"
would output something like "Alexa would love an Apple!".Extensibility
C# mods can define custom tokens by calling
TokenParser.RegisterParser("tokenName", ...)
. To avoid conflicts, prefixing custom condition names with your mod ID (like Example.ModId_TokenName) is strongly recommended.Event changes
Major changes:
Event IDs are now strings, so mods can use a unique key instead of hoping no other mod uses the same number. Unconditional events must have an empty precondition in their key (like "Example.ModId_EventName/") to distinguish them from forks.
Prefixing the event ID with your mod ID is recommended to simplify troubleshooting and avoid conflicts. For best compatibility, custom IDs should only contain alphanumeric/underscore/dot characters.
- Added validation for event preconditions & commands. If a format or assumption is invalid, the game now logs a detailed error and (if applicable) skips the command, instead of crashing or silently ignoring it. This also means event arguments are stricter (e.g. you can no longer set a true/false field to an invalid value, inner quotes in quoted arguments now need to be escaped, etc).
- Event commands & preconditions are now quote-aware, so you can escape spaces and slashes in arguments like
/speak "I'm running A/B tests"/
. - Event commands now trim surrounding whitespace, so they can be multilined for readability. For example:
"SomeEventId/": " none/-1000 -1000/farmer 5 7 0/ skippable/ viewport 5 7 10/ ... "
- Event/festival commands with a direction argument now allow both case-insensitive names (like up) and numeric values.
- C# mods can now add custom event preconditions & commands using Event.RegisterCustomPrecondition and Event.RegisterCustomCommand respectively.
- Added new preconditions:
precondition description ! Prefixing ! to any other precondition will now invert it. For example, !O Abigail
will match if the player is not married to Abigail.G Check the result of a game state query, like G !WEATHER Here Sun
for 'not sunny in this location'. - Added new event commands:
command description addItem <item ID>
[count]
[quality]
Add an item to the player inventory (or open a grab menu if their inventory is full). The <item ID>
is the qualified or unqualified item ID, and[quality]
is a numeric quality value.addSpecialOrder <order ID>
removeSpecialOrder<order ID>
Add or remove a special order to the player team. This affects all players, since special orders are shared. mailToday <mail key>
Adds a letter to the mailbox immediately, given the <mail key>
in Data/Mail.stopSound <sound ID>
[immediate]
Stop a sound started with the startSound command. This has no effect if the sound has already stopped playing on its own (or hasn't been started). If you started multiple sounds with the same ID, this will stop all of them (e.g. startSound fuse/startSound fuse/stopSound fuse
).By default the sound will stop immediately. For looping sounds, you can pass false to the
[immediate]
argument to stop the sound when it finishes playing the current iteration instead (e.g.stopSound fuse false
).temporaryAnimatedSprite ... Add a temporary animated sprite to the event, using these space-delimited fields: index field effect 0 texture The asset name for texture to draw. 1–4 rectangle The pixel area within the texture to draw, in the form <x>
<y>
<width>
<height>
.5 interval The millisecond duration for each frame in the animation. 6 frames The number of frames in the animation. 7 loops The number of times to repeat the animation. 8–9 tile The tile position at which to draw the sprite, in the form <x>
<y>
.10 flicker [TODO: document what this does] (one of true or false). 11 flip Whether to flip the sprite horizontally when it's drawn (one of true or false). 12 sort tile Y The tile Y position to use in the layer depth calculation, which affects which sprite is drawn on top if two sprites overlap. 13 alpha fade [TODO: document what this does] 14 scale A multiplier applied to the sprite size (in addition to the normal 4× pixel zoom). 15 scale change [TODO: document what this does] 16 rotation The rotation to apply to the sprite, measured in radians. 17 rotation change [TODO: document what this does] 18+ flags Any combination of these space-delimited flags: - color
<color>
: apply a standard color to the sprite. - hold_last_frame: after playing the animation once, freeze the last frame as long as the sprite is shown.
- ping_pong: [TODO: document what this does]
- motion
<x>
<y>
: [TODO: document what this does] - acceleration
<x>
<y>
: [TODO: document what this does] - acceleration_change
<x>
<y>
: [TODO: document what this does]
translateName <actor>
<translation key>
Set the display name for an NPC in the event to match the given translation key. warpFarmers [ <x>
<y>
<direction>
]+<default offset>
<default x>
<default>
<direction>
Warps connected players to the given tile coordinates and numeric directions. The <x>
<y>
<direction>
triplet is repeated for each connected player (e.g. the first triplet is for the main player, second triplet is for the first farmhand, etc). The triplets are followed by an offset direction (one of up, down, left, or right), and a final triplet which defines the default values used by any other player. - color
Improved preconditions:
- The h precondition can now be used with any pet type. You can also omit the argument to check for a pet of any type.
Improved commands:
- Fixed some commands assuming a boolean argument is true if present, regardless of its value. This affects the changeToTemporaryMap, emote, extendSourceRect, faceDirection, globalFade, globalFadeToClear, positionOffset, and warp commands.
- Fixed some commands assuming any value except the exact case-sensitive string true is false. This affects the animate, glow, hideShadow, ignoreMovementAnimation, temporaryAnimatedSprite, temporarySprite, and viewport commands.
- Fixed some commands silently ignoring values they can't parse as the expected type. This affects the addItem, makeInvisible, and removeItem commands.
- Fixed crash when some commands are passed farmer[number] for a player who's not available, or farmer[number] when they expect farmer.
- Fixed some commands not taking into account custom farmer actors when checking farmer* actor IDs.
- Changed specific commands:
command changes addCookingRecipe Fixed error if player already knows the recipe. addTemporaryActor - Underscores in the asset name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like
addTemporaryActor "White Chicken" …
. - Underscores in the display name are no longer replaced with spaces. You should quote arguments containing spaces instead.
animate Underscores in the NPC name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like animate "Mr Qi" …
.ambientLight Removed four-argument form (which was unused and had confusing behavior). The other versions of ambientLight still work like before. awardFestivalPrize Added support for arbitrary item IDs, like awardFestivalPrize (O)128
for a pufferfish.changeName Underscores in the NPC name are no longer replaced with spaces. You should quote arguments containing spaces instead, like changeName Leo "Neo Leo"
.changePortrait
changeSpriteYou can now omit the suffix argument to reset the NPC back to their normal portrait/sprite. ignoreMovementAnimation - Fixed its ignore argument being ignored.
- Underscores in the NPC name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like
ignoreMovementAnimation "Mr Qi" …
.
itemAboveHead Added support for arbitrary item IDs, like itemAboveHead (O)128
for a pufferfish.makeInvisible Fixed terrain features not hidden when using the default area size. removeItem Added argument for an optional count, like removeItem (O)128 10
to remove 10 pufferfish.speak Fixed friendship & socialize quest not updated when calling it with a translation key. weddingSprite Removed (it was broken and unused). - Underscores in the asset name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like
Other improvements:
- Festivals now set the event ID to a value like festival_fall16, instead of -1.
- For C# mods, the new Event.fromAssetName field indicates which data asset (if any) the event was loaded from.
- Event script errors are now logged (in addition to being shown in the chatbox like before).
- Fixed NPCs getting duplicated in festivals if they're added to the set-up fields multiple times. Subsequent entries now move them instead.
Mail changes
- Mail can now have multiple items attached (using multiple %item commands). When the player grabs the top item, the next one will appear in the slot to grab next.
- Improved mail commands:
command changes %item - Added %item id
<item id>
[count]
form which accepts a qualified or unqualified item ID. If multiple items are listed (e.g., %item id (BC)12 3 (O)34 5 %%) one set will be picked randomly. This deprecates the bigobject, furniture, object, and tools options. - Added %item specialOrder
<order id>
[immediately]
form to attach a special order to the letter. - Added optional
<key>
argument to %item cookingRecipe<key>
, to learn a specific cooking recipe. The previous %item cookingRecipe form (without a key) works the same way as before. - The type argument is now case-insensitive.
- Fixed %item craftingRecipe not supporting recipe IDs containing underscores. It now checks for an exact match first, then tries replacing underscores with spaces like before, then logs a warning if neither was found instead of adding an invalid recipe.
- Added %item id
New C# utility methods
Stardew Valley 1.6 adds several new methods to simplify common logic.
Argument handling
The new ArgUtility class handles splitting, reading, and validating string[] argument lists. The main methods are:
- Splitting arrays:
ArgUtility method effect SplitBySpace Split space-separated arguments in a string. This automatically ignores extra spaces, so " x y " and "x y" are equivalent. For example: string[] fields = ArgUtility.SplitBySpace("a b c"); string secondField = fields[1]; // "b"
SplitBySpaceAndGet Get the value at an index in a space-delimited string (if found), else return the default value. For example: string thirdField = ArgUtility.SplitBySpaceAndGet("a b c", 2); // "c" string invalidFieldA = ArgUtility.SplitBySpaceAndGet("a b c", 5); // null string invalidFieldB = ArgUtility.SplitBySpaceAndGet("a b c", 5, defaultValue: "boop"); // "boop"
This is more efficient than SplitBySpace when you only need a single value, but it's slower if you need multiple values.
SplitBySpaceQuoteAware Split space-separated arguments in a string, with support for using quotes to protect spaces within an argument. See SplitQuoteAware below for info on quote handling. For example:
string buildingName = ArgUtility.SplitBySpaceQuoteAware("BUILDINGS_CONSTRUCTED Here \"Junimo Hut\"")[1]; // Junimo Hut
SplitQuoteAware Split delimited arguments in a string, with support for using quotes to protect delimiters within an argument. A quote in the text causes any delimiter to be ignored until the next quote, unless it's escaped like
\"
. Unescaped quotes are removed from the string. (Remember that backslashes need to be escaped in C# or JSON strings, like"\\"
for a single backslash.)For example:
ArgUtility.SplitQuoteAware("A,B,C", ','); // [ "A", "B", "C" ] ArgUtility.SplitQuoteAware("A,\"B,C\",D", ','); // [ "A", "B,C", "D" ] ArgUtility.SplitQuoteAware("A,\\\"B,C", ','); // [ "A", "\"B", "C" ]
You can also set the optional arguments for more advanced cases. For example, game state queries use this to split twice:
string gameStateQuery = "BUILDINGS_CONSTRUCTED Here \"Junimo Hut\", SEASON Spring"; string[] queries = ArgUtility.SplitQuoteAware(gameStateQuery, ',', StringSplitOptions.RemoveEmptyEntries, keepQuotesAndEscapes: true); // [ "BUILDINGS_CONSTRUCTED Here \"Junimo Hut\"", "SEASON Spring" ] string buildingName = ArgUtility.SplitBySpaceQuoteAware(queries[0]); // Junimo Hut
EscapeQuotes Escape quotes in a string so they're ignored by methods like SplitQuoteAware. This isn't idempotent (e.g. calling it twice will result in double-escaped quotes).
- Reading arrays:
ArgUtility method effect HasIndex Get whether an index is within the bounds of the array. For example: string[] fields = ArgUtility.SplitByString("10 5"); bool inRange = ArgUtility.HasIndex(fields, 1); // true (index 1 has the value '5')
Get
GetBool
GetDirection
GetEnum
GetFloat
GetIntGet the value at a position in an array, parsed as the relevant type (e.g. a string, boolean, direction, enum, etc). If the index isn't in the array or the value can't be parsed as the expected type, returns a default value. For example, code like this:
int value = fields.Length > 4 && int.TryParse(fields[4], out int parsed) ? parsed : -1;
Can now be rewritten like this:
int value = ArgUtility.GetInt(fields, 4, -1);
TryGet
TryGetBool
TryGetDirection
TryGetEnum
TryGetFloat
TryGetInt
TryGetPoint
TryGetRectangle
TryGetVector2Try to get a parsed value from an array by its index. If it's not found or can't be converted to the expected value, it sets the out string error argument so you can log an error if needed. For example, this parses a numeric value from a space-delimited string:
string[] fields = ArgUtility.SplitByString("10 35"); if (ArgUtility.TryGetInt(fields, 1, out int value, out string error)) this.Helper.Monitor.Log($"Parsed value: {value}"); // "Parsed value: 35" else this.Helper.Monitor.Log($"Failed parsing value: {error}", LogLevel.Warn);
TryGetOptional
TryGetOptionalBool
TryGetOptionalDirection
TryGetOptionalEnum
TryGetOptionalFloat
TryGetOptionalInt
TryGetOptionalRemainderEquivalent to TryGet*, except that it'll return a default value if the argument is missing. For example: string[] fields = ArgUtility.SplitByString("10"); if (ArgUtility.TryGetOptionalInt(fields, 1, out int value, out error, defaultValue: 99)) this.Helper.Monitor.Log($"Parsed value: {value}"); // "Parsed value: 99" else this.Helper.Monitor.Log($"Failed parsing value: {error}", LogLevel.Warn);
GetRemainder
TryGetRemainder
TryGetOptionalRemainderSimilar to the previous methods, but gets arguments starting from an index as a concatenated string. For example: string[] fields = ArgUtility.SplitByString("A B C D E F"); if (ArgUtility.TryGetRemainder(fields, 2, out string remainder, out string error)) this.Helper.Monitor.Log($"Remainder: {remainder}"); // "Remainder: C D E F" else this.Helper.Monitor.Log($"Failed getting remainder: {error}", LogLevel.Warn);
Content assets
method effect LocalizedContentManager.DoesAssetExist Get whether an asset exists in the game's Content folder or is provided through SMAPI's content API. For example: bool exists = Game1.content.DoesAssetExist<Map>("Maps/Town");
LocalizedContentManager.IsValidTranslationKey Get whether a string is a translation key in the form <asset name>
:<key>
, and the asset and key both exist. For example:bool exists = Game1.content.IsValidTranslationKey("Strings\\NPCNames:Abigail");
Game paths
The game folder paths were previously hardcoded throughout the code. These are now centralized with a few methods:
method effect Program.GetLocalAppDataFolder
Program.GetAppDataFolderGet the absolute path to the game's app data folder (which contains the Saves folder) or local app data folder (which contains ErrorLogs and Screenshots). These methods are equivalent on Windows, but different on Linux/macOS. Program.GetSavesFolder Get the absolute path to the game's Saves folder. Game1.GetScreenshotFolder Get the absolute path to the game's Screenshots folder. options.GetFilePathForDefaultOptions Get the absolute path to the game's default_options file. Iteration
The new Utility.ForEach* methods let you check every thing of a type in the game world quickly and efficiently (with minimal allocations, boxing, etc). These are significantly faster than equivalent code using LINQ or yield methods.
method effect Utility.ForEachBuilding Perform an action for each building in the game world. Utility.ForEachCharacter
Utility.ForEachVillagerPerform an action for each NPC in the game world. ForEachCharacter matches all NPC types (villagers, horses, pets, monsters, player children, etc), while ForEachVillager only matches villager NPCs like Abigail. Utility.ForEachCrop Perform an action for each crop in the game world planted in the ground or in a garden pot. Utility.ForEachItem Perform an action for each item in the game world, including items within items (e.g. in a chest or on a table), hats placed on children, items in player inventories, etc. Utility.ForEachItemIn Perform an action for each item within a given location, including items within items (e.g. in a chest or on a table). Utility.ForEachLocation Perform an action for each location in the game world, optionally including building interiors and generated mine or volcano levels. For example, this code counts how many parsnips are planted everywhere in the world:
int parsnips = 0; Utility.ForEachCrop(crop => { if (crop.IndexOfHarvest == "24") parsnips++; return true; // whether to keep iterating after this crop });
C# mods which add custom item types can override Item.ForEachItem to add support for nested items.
Randomization
method effect Utility.CreateDaySaveRandom Creates a Random instance using the most common seed (based on the save ID and total days played). Utility.CreateRandom
Utility.CreateRandomSeedCreates a Random (or seed for a Random) by combining the given seed values, which can be any numeric type. Utility.TryCreateIntervalRandom Get an RNG which produces identical results for all RNGs created with the same sync key during the given interval (one of tick, day, season, or year), including between players in multiplayer mode. For example, this will return the same number each time it's called until the in-game day changes:
public int GetDailyRandomNumber() { Utility.TryCreateIntervalRandom("day", "example sync key", out Random random, out _); return random.Next(); }
Utility.TryGetRandom Get a random entry from a dictionary. random.Choose Choose a random option from the values provided: string npcName = Game1.random.Choose("Abigail", "Penny", "Sam");
random.ChooseFrom Choose a random option from a list or array: string[] names = new[] { "Abigail", "Penny", "Sam" }; string npcName = Game1.random.ChooseFrom(names);
random.NextBool Randomly choose true or false. For example: bool flipSprite = Game1.random.NextBool();
You can optionally set the probability of true:
bool flipSprite = Game1.random.NextBool(0.8);
Other
Here are some of the other new methods:
method effect Utility.distanceFromScreen Get the pixel distance between a position in the world and the player's screen viewport, where 0 is within the viewport. Utility.DrawErrorTexture Draw the game's missing-texture image (🚫) to the screen, stretched to fit a given pixel area. Utility.GetEnumOrDefault Get an enum value if it's valid, else get a default value. This is mainly used to validate input from data files. For example:
NpcGender gender = (NPCGender)999999; gender = Utility.GetEnumOrDefault(gender, Gender.Male); // returns Gender.Male since there's no enum constant with value 999999
Utility.getRandomNpcFromHomeRegion Get a random social NPC based on their HomeRegion value in Data/Characters. For example, this gets a random NPC for the Town home region: NPC npc = Utility.getRandomNpcFromHomeRegion(NPC.region_town);
Utility.isFestivalDay
Utility.IsPassiveFestivalDayThese methods existed before 1.6, but now have versions with no arguments to check today: bool festivalToday = Utility.isFestivalToday();
IsPassiveFestivalDay also has a new form to check for a specific festival today:
bool nightMarketToday = Utility.IsPassiveFestivalDay("NightMarket");
Utility.TryGetPassiveFestivalData
Utility.TryGetPassiveFestivalDataForDayGet the passive festival data for the given ID or date. Utility.TryParseDirection Parse a string into a direction value (like Game1.down), if it's valid. This supports case-insensitive direction names (one of down, left, right, or up) or numeric values. Utility.TryParseEnum Parse a string into an enum value if possible, case-insensitively. Unlike Enum.TryParse, an invalid numeric value won't be cast: Enum.TryParse("999999", out DayOfWeek day); // true, even though there's no matching DayOfWeek value Utility.TryParseEnum("999999", out DayOfWeek day); // false
Utility.fuzzyCompare Get whether a term is a fuzzy match for a search query. Returns the numeric match priority (where lower values are a better match), or null if the term doesn't match the query. rectangle.GetPoints
rectangle.GetVectorsGet all the integer coordinates within a given Rectangle. For example: var tileArea = new Rectangle(0, 0, 2, 2); Point[] tiles = tileArea.GetPoints(); // (0, 0), (1, 0), (0, 1), (1, 1)
Utility.GetDeterministicHashCode (Specialized) Get a hash code for a string key or numeric values. Unlike string.GetHashCode or HashCode.Combine, this produces a consistent hash for the same inputs between sessions and connected players. Utility.WrapIndex Constrain an index to a range by wrapping out-of-bounds values to the other side (e.g. last index + 1 is the first index, and first index - 1 is the last one). For example:
string[] values = new[] { "0", "1", "2" }; int index = Utility.WrapIndex(-1, values.Length); // 2
Static delegate builder
For C# mods, StaticDelegateBuilder is a specialized class which converts a method name into an optimized delegate which can be called by code. This is used by vanilla code to optimize methods referenced in assets like Data/Machines.
For example, given a static method like this:
public static bool OutputDeconstructor(Object machine, Item inputItem, bool probe, MachineItemOutput outputData, out int? overrideMinutesUntilReady) { ... }
And a delegate which matches it:
public delegate bool MachineOutputDelegate(Object machine, Item inputItem, bool probe, MachineItemOutput outputData, out int? overrideMinutesUntilReady);
You can create an optimized delegate and call it like this:
if (StaticDelegateBuilder.TryCreateDelegate("StardewValley.Object.OutputDeconstructor", out MachineOutputDelegate method, out string error)) return method(this, inputItem, probe, outputData, out minutesUntilMorning); else Game1.log.Warn($"Machine {ItemId} has invalid output method: {error}");
The TryCreateDelegate method will cache created delegates, so calling it again will just return the same delegate instance.
Game logging changes
The game now writes debug output through an internal Game1.log wrapper, instead of using Console.WriteLine directly. For example:
// old code Console.WriteLine("Error playing sound: " + ex); // new code Game1.log.Error("Error playing sound.", ex);
This has a few benefits:
- For vanilla players, the game no longer uses time & resources writing to a console that's not visible anyway.
- For modded players, SMAPI can now...
- distinguish between the game's debug/warn/error messages (so many warnings/errors that would previously appear as hidden TRACE messages will now be shown with the correct level);
- apply its formatting rules to exceptions logged by the game too;
- redirect game output much more efficiently without console interception.
Other changes
Audio
- Added Game1.sounds, which unifies the high-level sound effect logic (e.g. distance fading and multiplayer sync).
- Added silence audio cue for music. This is different from none in that it suppresses both town music and ambient sounds.
- Added Game1.soundBank.Exists(cueName) method to check if an audio cue exists.
- Added Game1.playSound overloads to get the audio cue being played.
- Added character.playNearbySoundAll and playNearbySoundAllLocal methods to play a sound for players near the player/character.
- Added position argument to DelayedAction.playSoundAfterDelay.
- Removed NetAudioCueManager and Game1.locationCues (unused).
- Unified the methods for playing normal/pitched/positional sounds (which also adds support for pitched non-synced & pitched positional sounds):
old methods new method Game1.playSound
Game1.playSoundAt
Game1.playSoundPitchedGame1.playSound GameLocation.playSound
GameLocation.playSoundAt
GameLocation.playSoundPitchedGameLocation.playSound GameLocation.localSound
GameLocation.localSoundAtGameLocation.localSound NetAudio.Play
NetAudio.PlayAt
NetAudio.PlayPitchedNetAudio.Play NetAudio.PlayLocal
NetAudio.PlayLocalAtNetAudio.PlayLocal
Debug commands
- All debug commands are now quote-aware, so you can pass spaces in arguments like
debug build "Junimo Hut"
. - Added new debug commands:
command description bsm If the player is standing right under a building, open a menu to change the building appearance. exportShops Export a summary of what's in every shop in the game, taking into account their current conditions. This is saved to a file on disk, and the file path shown in the console. filterLoadMenu / flm Syntax: filterLoadMenu <search text>
Filter the current list of saves to those whose player name or farm name contains the given text.
forcebuild Equivalent to build, but disables all safety checks so you can build in a location that wouldn't normally allow buildings, build on top of farm animals or placed objects, etc. gamequery / gq Syntax: gq <query>
Check whether the given game state query matches in the current context. For example:
gq !SEASON Spring, WEATHER Here Sun > Result: true.
itemquery / iq Syntax: iq <query>
Open a shop menu with all the items matching an item query (all items free). For example:
- debug iq ALL_ITEMS shows all items;
- debug iq ALL_ITEMS (W) shows all weapons;
- debug iq (O)128 shows a pufferfish (object 128);
- debug iq FLAVORED_ITEM Wine (O)128 shows Pufferfish Wine.
legacyTimeouts Switches the multiplayer timeout behavior between legacy (timeouts are based on both ping time and last sync time like in 1.5.6) and non-legacy (timeouts are only based on ping time). logSounds Log info about each sound effect played to the SMAPI console window. qualifiedid Print the held item's display name and qualified item ID. shop Syntax: shop <shop ID>
[owner name]
Open a shop defined in Data/Shops, regardless of whether one of the owners is nearby. Specifying
[owner name]
will use that NPC, otherwise the command will find the closest valid NPC if possible (else open with no NPC).testwedding Immediately play the wedding event. thishouseupgrade / thishouse / thu Equivalent to houseupgrade, but can be used to upgrade another player's house by running it from inside or just south of its exterior. tokens Syntax: tokens <tokenized string>
Parses a tokenizable string and prints its output. For example:
tokens [LocalizedText Strings\StringsFromCSFiles:MapPage.cs.11064 [EscapedText [FarmName]]] > Result: "Lon Lon Farm"
- Improved existing debug commands:
command changes build Removed custom space handling; quote arguments with spaces instead of replacing them with 9 (e.g. Junimo9Hut
→"Junimo Hut"
).clearFurniture Now works outside the farmhouse too. dialogue Removed custom space handling; quote NPC names containing spaces instead, with all text after the first argument treated as part of the dialogue (e.g. debug dialogue "Some NPC" Some dialogue text$h
).ebi Fixed event not played correctly if called from the same location as the event. fish Fixed error if you're not holding a fishing rod. It now opens the fishing minigame with no tackle instead. frameOffset - Simplified usage. You can now pass negative offsets directly (like debug frameOffset -5 -10) instead of using the s number prefix.
- Fixed command only taking the last digit in each number.
getStat
setStatAdded validation for the stat name. grass Now applies to the current location, instead of the farm. growAnimals
growAnimalsFarmMerged into one growAnimals command that supports any location and doesn't reset the age of animals which are already adults. growCrops Fixed error growing mixed seeds or giant crops. itemNamed Removed custom space handling; quote arguments with spaces instead of removing them (e.g. EelRoe
→"Eel Roe"
).junimoGoodbye
junimoStarAdded validation to check that you're inside the community center. killAll
killAllHorses
killNpcThese now remove matching NPCs inside constructed buildings too. killMonsterStat Removed custom space handling; quote arguments with spaces instead of replacing them with 0 (e.g. Dust0Spirit
→"Dust Spirit"
).mailForTomorrow Fixed zeros in the mail ID getting replaced with underscores. monster Added validation for the monster name. moveBuilding Now applies to the current location, instead of the farm. movie Rewritten; it's now simpler, applies the normal game logic, defaults to today's movie, and avoids depending on NPC indexes in Data/NPCDispositions since those can change with custom NPCs. New usage:
- debug movie
[movie ID]
[invite NPC name]
- debug movie current
[invite NPC name]
The movie ID defaults to today's movie, and the NPC name can be omitted to watch the movie without an invitee. Specifying current as the movie uses the default value.
panMode The command no longer overrides debug command handling while it's active. Instead you can now turn it back off by running debug panMode again, clear with debug panMode clear, or set a time with debug panMode {time}. paintBuilding - Now applies to the current location, instead of the farm.
- Added validation for the target building.
playSound Added an optional pitch argument, like debug playSound barrelBreak 1200. The pitch is a value from 1 (low pitch) to 2400 (high pitch) inclusively. skinBuilding - Now applies to the current location, instead of the farm.
- Added validation for the target building.
skullGear - Fixed command setting 32 slots instead of 36.
- Fixed command not adding empty inventory slots as expected by some game code.
setupFishPondFarm Fixed error if the farm already has non-fish-pond buildings constructed. speech Removed custom space handling; quote NPC names containing spaces instead, with all text after the first argument treated as part of the dialogue (e.g. debug speech "Some NPC" Some dialogue text$h
).spreadDirt Now applies to the current location, instead of the farm. spreadSeeds Now applies to the current location, instead of the farm. thisHouseUpgrade Now applies to the current location, instead of the farm. warpToPlayer Removed custom space handling; quote arguments with spaces instead of removing them (e.g. JohnSmith
→"John Smith"
).whereIs Now lists all matching NPCs instead of the first one. - Removed some debug commands:
command notes ax
bigItem/b/bi/big
boots
clothes
hoe
milkPail/mp
pan
pickaxe/pick/pickax
ring/addRing
shears/scissors
slingshot
tool
wateringCan/can
wand
weaponThese are replaced by more general commands like item (O)128
(spawn item by ID),fuzzyItemNamed pufferfish
(spawn by item name), oritemQuery FLAVORED_ITEM Wine (O)128
(spawn by item query).addQuartz
blueBook
blueprintThese were part of unused features removed in 1.6. oldMineGame Removed along with the pre-1.4 Junimo Kart code. pathSpouseToMe/pstm Removed along with the unimplemented farm activities code. - Added alternative names for some debug commands (new names in parentheses): bpm + bsm (paintBuilding + skinBuilding), craftingRecipe (addCraftingRecipe), db (speakTo), dialogue (addDialogue), pdb (printGemBirds), r (resetForPlayerEntry), removeLargeTf (removeLargeTerrainFeature), sb (showTextAboveHead), sl + sr (shiftToolbarLeft + shiftToolbarRight), sn (secretNote), and tls (toggleLightingScale).
- Reworked how debug commands log output. This fixes an issue where they don't always log to the right place (e.g. a command run through the chatbox might log to the console or vice-versa), and lets mods pass a custom logger to capture or redirect output.
Location logic
- The desert no longer assumes the player arrived by bus unless their previous location was the bus stop.
- The ticket price for the bus and Willy's boat can now be edited by C# mods via BusStop.TicketPrice and BoatTunnel.TicketPrice respectively.
Menus & UI
- Rewrote calendar menu (Billboard) to simplify custom events & event types. C# mods can now edit billboard.calendarDayData or patch billboard.GetEventsForDay to add new events.
- The SpriteText methods now accept arbitrary Color tints instead of a few predefined color IDs.
- Added Game1.textShadowDarkerColor field for the colors previously hardcoded in Utility.drawTextWithShadow.
- Added MoneyDial.ShouldShakeMainMoneyBox field to simplify custom dials.
- Fixed an edge case where a custom language's fonts wouldn't be loaded when switching language.
Net fields
- Removed implicit conversion operators for most types (except NetBool, NetInt, and NetString).
- NetLocationRef now has a public LocationName and IsStructure, and its Update method allows forcing an update.
Quests
- Quests now have string IDs, to simplify custom quest frameworks.
- Added validation for quest data parsing.
- In Data/SpecialOrders, the Duration and Repeatable fields are now strongly-typed and case-insensitive.
- For C# mods, fixed DescriptionElement not allowing more than four translation token substitutions.
Seasons
- Added a Season enum for strongly-typed, case-insensitive season checks (like
Game1.season == Season.Spring
instead ofGame1.currentSeason == "spring"
). - Added Game1.season, Game1.GetSeasonForLocation, Game1.WorldDate.Season, and location.GetSeason() to get the season enum.
- Added Utility.getSeasonKey to get the key form from a season enum.
- Renamed some members for clarity (Game1.GetSeasonForLocation → GetSeasonKeyForLocation, location.GetSeasonForLocation → GetSeasonKey, WorldDate.Season → SeasonKey).
- Fixed location.GetSeasonKey() not applying the greenhouse logic.
Time
- For C# mods, the Game1.realMilliSecondsPerGame and Game1.realMilliSecondsPerGameTenMinutes fields are no longer marked const, and the GameLocation.getExtraMillisecondsPerInGameMinuteForThisLocation() method has been replaced with a settable ExtraMillisecondsPerInGameMinute property. That lets you change the time rate used by the vanilla game code, but you should be careful doing this since it may cause unintended effects.
Other
- Error stack traces on Linux/macOS now have line numbers.
- All space-delimited fields now ignore extra spaces instead of crashing. This affects map/tile properties, data assets, event commands, game state queries, etc.
- All players and NPCs now have Tile & TilePoint properties (their cached tile position) and a StandingPixel property (the cached pixel coordinate at the center of their bounding box). These replace various deleted methods.
- All terrain features now have Tile and Location properties, and their methods no longer have location/tile parameters in most cases.
- All net fields now have Name and Owner fields, which are used to show informative error messages when there's a sync issue and validate common mistakes (e.g. a net field not added to the NetFields collection).
- Added C# code docs in many places.
- Added Id fields to simplify content pack edits in fish pond, movie concession, random bundle, and tailoring recipe data.
- Added Game1.Multiplayer to get the game's low-level handler. (Most code should still use SMAPI's multiplayer API though.)
- Added Game1.versionBuildNumber with the build number (like 26039).
- Added field-changed events to NetPosition.
- Added LocalizedContentManager.CurrentLanguageString, which caches the language code like pt-BR).
- The game now uses [XmlInclude] on its types more consistently. That means the default save serializer can handle more types (e.g. all monsters), and it's easier to create custom serializers.
- Refactored many parts of the code to make it more moddable for C# mods. This includes marking all classes public, changing private members to protected or public, marking members virtual, rewriting or splitting code so it's easier to extend, etc.
- Fixed many cases where the game used Game1.player instead of the provided player.
Breaking changes for C# mods
This section only describes how this update may break existing mods. See the what's new sections above for more info, including new functionality mods can use.
See also Breaking changes for content packs, which affect C# mods too.
.NET 6
- See also: .NET 6 under what's new.
Stardew Valley 1.6 updates from .NET 5 to .NET 6. SMAPI can still load .NET 5 mods fine, but you'll get a build error when compiling them. To update a C# mod:
- Make sure you have Visual Studio Community 2022 or later. (Compiling .NET 6 with earlier versions of Visual Studio isn't officially supported.)
- In Visual Studio, click Help > Check For Updates and install the latest version.
- Fully exit Visual Studio.
- Open each mod's .csproj file in a text editor, then find this line:
<TargetFramework>net5.0</TargetFramework>
And change it to this:
<TargetFramework>net6.0</TargetFramework>
- Delete your solution's hidden .vs folder, and every project's bin and obj folders.
- Reopen the solution in Visual Studio, click Build > Rebuild Solution, and make sure it still loads into the game fine.
Item ID changes
- See also: custom items in what's new.
The main Item properties have changed. To migrate existing code:
- Don't use ParentSheetIndex to compare items. For example, item.ParentSheetIndex == 0 will match both weeds and any custom item whose sprite is the first one in its custom spritesheet. You should compare items using their new ItemId and QualifiedItemId properties instead. For example, here's how to migrate various common forms:
old code new code item.ParentSheetIndex == 848 item.QualifiedItemId == "(O)848" IsNormalObjectAtParentSheetIndex(item, 74) item.QualifiedItemId == "(O)74" !item.bigCraftable && item.ParentSheetIndex == 128 item.QualifiedItemId == "(O)128" item is Boots && item.ParentSheetIndex == 505 item.QualifiedItemId == "(B)505" - Don't assume item sprites are in the vanilla spritesheets. For example, instead of rendering Game1.objectSpriteSheet for an object, call
ItemRegistry.GetMetadata(item.QualifiedItemId).GetTexture()
to get its texture. - Creating items works just like before, except that you now specify the item's ItemId (not QualifiedItemId) instead of its ParentSheetIndex. This is the same value for vanilla items. For example:
new Object("634", 1); // vanilla item new Object("Example.ModId_Watermelon", 1); // custom item
You can also use the new ItemRegistry API to construct items from their QualifiedItemId:
Item item = ItemRegistry.Create("(B)505"); // Rubber Boots
Other ID changes
Many other things in the game now have unique string IDs too (including buffs, events, and fruit trees). To migrate existing code:
- When referencing numeric IDs, you usually just need to convert them into a string (like
Game1.player.hasBuff("1590166")
orGame1.player.eventsSeen.Contains("1590166")
). - When creating buffs, see buff overhaul for how to create buffs now.
Building and animal changes
- See also: build anywhere in what's new.
- Since all locations now allow buildings and animals, mod code which handles BuildableGameLocation and IAnimalLocation won't detect all buildable locations. You can replace them with location.IsBuildableLocation() (or just access location.buildings directly) and location.animals.Any() instead. Mods should no longer have any reference at all to BuildableGameLocation and IAnimalLocation.
- Since buildings can be built anywhere, you can no longer assume a building is on the farm. You can check the new building.buildingLocation field instead.
- You should review direct references to the farm (like
Game1.getFarm()
orGame1.getLocationFromName("Farm")
) to see if it needs to be rewritten to allow other locations. Utility.numSilos()
should no longer be used to calculate available hay, since it doesn't account for custom buildings with hay storage. UseGame1.getFarm().GetHayCapacity()
instead.- The Cat and Dog classes are now unused; all pets are now Pet directly.
Player changes
- See also: buff overhaul in what's new.
- Several Game1.player / Farmer fields changed as part of the buff overhaul:
old field how to migrate appliedBuffs
appliedSpecialBuffsUse Game1.player.hasBuff(id)
instead.attack
immunityUse Attack and Immunity instead. addedCombatLevel
addedFarmingLevel
addedFishingLevel
addedForagingLevel
addedLuckLevel
addedMiningLevel
attackIncreaseModifier
critChanceModifier
critPowerModifier
knockbackModifier
resilience
weaponPrecisionModifier
weaponSpeedModifierUse equivalent properties under Game1.player.buffs instead (e.g. Game1.player.buffs.CombatLevel). addedSpeed
CombatLevel
CraftingTime
FarmingLevel
FishingLevel
ForagingLevel
LuckLevel
MagneticRadius
MaxStamina
MiningLevel
StaminaThese are now readonly and can't be set directly. You can change them by adding a buff, equipment bonus, etc instead. - Buffs are now recalculated automatically, and you can reset a buff by just reapplying it. See buff overhaul for more info.
- Buff logic has been centralized into Game1.player.buffs. This replaces a number of former fields/methods like Game1.buffsDisplay.
Collision changes
The game's tile collision logic has been overhauled and merged into a simpler set of methods on GameLocation instances:
method effect CanSpawnCharacterHere Get whether NPCs can be placed on the given tile (e.g. it's within the map bounds and tile is walkable), there's no placed object there, and the NoFurniture tile property isn't set. CanItemBePlacedHere Get whether items can be placed on the given tile in non-floating form (e.g. it's within the map bounds and not blocked by a non-walkable item), and the NoFurniture tile property isn't set. isBuildable Get whether buildings can be placed on the given tile. IsTilePassable Get whether the tile can be walked on (ignoring collisions with in-game objects, NPCs, etc). IsTileOccupiedBy Get whether the tile contains a player, object, NPC/monster/pet/etc, terrain feature, building, etc. You can choose which entities to check, and which ones to ignore if they don't block movement. IsTileBlockedBy Equivalent to calling both IsTilePassable and IsTileOccupiedBy. IsLocationSpecificOccupantOnTile
IsLocationSpecificPlacementRestrictionGenerally shouldn't be used directly. Checks for location-specific collisions (e.g. ladders in the mines or parrot platforms on Ginger Island). 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 unused code
1.6 removes a lot of unused code. That includes these classes:
namespace class name StardewValley - BuildingUpgrade
- DisposableList
- FurniturePlacer
- ListPool
- OneTimeRandom
StardewValley.Characters - BotchedNetBool
- BotchedNetField
- BotchedNetInt
- BotchedNetLong
StardewValley.Menus - FarmInfoPage
- MiniatureTerrainFeature
StardewValley.Monsters - LavaCrab
StardewValley.Objects - ObjectFactory (replaced by ItemRegistry)
StardewValley.TerrainFeatures - Quartz
StardewValley.Tools - Blueprints
- ToolFactory (replaced by ItemRegistry)
And these class members:
type members Axe - StumpStrength
Bush - alpha
- lastPlayerToHit
Chest - chestType
- coins
CosmeticPlant - scale
CraftingRecipe - itemType
Crop - daysOfUnclutteredGrowth
Farm - GetSpouseOutdoorAreaSpritesheetIndex()
FarmAnimal - homeLocation
Farmer - barnUpgradeLevel and BarnUpgradeLevel
- blueprints
- coalPieces and CoalPieces
- coopUpgradeLevel and CoopUpgradeLevel
- copperPieces and CopperPieces
- eyeColor
- feed and Feed
- furnitureOwned
- goldPieces and GoldPieces
- hasBusTicket
- hasGreenhouse
- iridiumPieces and IridiumPieces
- ironPieces and IronPieces
- newSkillPointsToSpend
- overallsColor
- ownsFurniture
- quartzPieces and QuartzPieces
- shirtColor
- skinColor
- stonePieces and StonePieces
- theaterBuildDate
- woodPieces and WoodPieces
Game1 - boardingBus
- chanceToRainTomorrow
- checkForNewLevelPerks
- cloud
- coopDwellerBorn
- cropsOfTheWeek
- currentBarnTexture
- currentBillboard
- currentCoopTexture
- currentFloor
- currentHouseTexture
- currentWallpaper
- dealerCalicoJackTotal
- FarmerFloor
- farmerWallpaper
- fertilizer
- floorPrice
- greenhouseTexture
- inMine
- jukeboxPlaying
- keyHelpString
- listeningForKeyControlDefinitions
- logoScreenTexture
- mailboxTexture
- menuChoice
- menuUp
- nameSelectUp
- nameSelectType
- numberOfSelectedItems
- particleRaining
- pickingTool
- pickToolDelay
- pickToolInterval
- priceOfSelectedItem
- progressBar
- selectedItemsType
- shiny
- shippingTax
- showKeyHelp
- slotResult
- startedJukeboxMusic
- tinyFontBorder
- toolIconBox
- tvStation
- tvStationTexture
- wallpaperPrice
GameLocation - boardBus(…)
- getWallDecorItem(…)
- removeBatch(…)
- removeDirt(…)
- removeStumpOrBoulder(…)
GiantCrop - forSale
IClickableMenu - currentRegion
MeleeWeapon - attackSwordCooldownTime
- doStabbingSwordFunction(…)
Monster - doHorizontalMovement(…)
- durationOfRandomMovements
- coinsToDrop
NPC - canReceiveThisItemAsGift(…)
- idForClones
Object - attachToSprinklerAttachment(…)
- canBePlacedInWater()
- consumeRecipe(…)
- isHoeDirt and IsHoeDirt
PathFindController - CheckClearance(…)
- limit
SaveGame - cropsOfTheWeek
- currentFloor
- currentWallpaper
- FarmerFloor
- farmerWallpaper
- shippingTax
Spiker - GetSpawnPosition
Stats - barsSmelted and BarsSmelted
Tool - batteredSwordSpriteIndex
- GetSecondaryEnchantmentCount()
- nonUpgradeable
- parsnipSpriteIndex
- Stackable
- startOfNegativeWeaponIndex
Utility - buyFloor()
- buyWallpaper()
- cropsOfTheWeek()
- getRandomSlotCharacter()
- plantCrops(…)
- showLanternBar()
Renamed classes
These classes were renamed in 1.6:
old name new name Game1.MusicContext MusicContext (in StardewValley.GameData) LocationContext LocationContexts SpecialOrder.QuestStatus SpecialOrderStatus (in StardewValley.SpecialOrders) And these were moved to a different namespace:
type old namespace new namespace AmethystEnchantment
AquamarineEnchantment
ArchaeologistEnchantment
ArtfulEnchantment
AutoHookEnchantment
AxeEnchantment
BaseEnchantment
BaseWeaponEnchantment
BottomlessEnchantment
BugKillerEnchantment
CrusaderEnchantment
DiamondEnchantment
EfficientToolEnchantment
EmeraldEnchantment
FishingRodEnchantment
GalaxySoulEnchantment
GenerousEnchantment
HaymakerEnchantment
HoeEnchantment
JadeEnchantment
MagicEnchantment
MasterEnchantment
MilkPailEnchantment
PanEnchantment
PickaxeEnchantment
PowerfulEnchantment
PreservingEnchantment
ReachingToolEnchantment
RubyEnchantment
ShavingEnchantment
ShearsEnchantment
SwiftToolEnchantment
TopazEnchantment
VampiricEnchantment
WateringCanEnchantmentStardewValley StardewValley.Enchantments Extensions StardewValley StardewValley.Extensions ModDataDictionary
ModHooksStardewValley StardewValley.Mods PathFindController
PathNode
PriorityQueue
SchedulePathDescriptionStardewValley StardewValley.Pathfinding SpecialOrder StardewValley StardewValley.SpecialOrders CollectObjective
DeliverObjective
DonateObjective
FishObjective
GiftObjective
JKScoreObjective
OrderObjective
ReachMineFloorObjective
ShipObjective
SlayObjectiveStardewValley StardewValley.SpecialOrders.Objectives FriendshipReward
GemsReward
MailReward
MoneyReward
OrderReward
ResetEventRewardStardewValley StardewValley.SpecialOrders.Rewards Other API changes
These class members changed in 1.6:
type member migration Bush overrideSeason Removed; use bush.currentLocation.GetSeason()
instead.greenhouseBush Removed; use bush.IsSheltered()
orbush.currentLocation.IsGreenhouse
instead.inBloom Remove the arguments, like bush.inBloom(Game1.currentSeason, Game1.dayOfMonth)
→bush.inBloom()
.Character getStandingX
getStandingY
getStandingXYRemoved; use character.StandingPixel instead. getTileLocation
getTileX
getTileY
Removed; use character.Tile instead. getTileLocationPoint Removed; use character.TilePoint instead. Farmer changePants Renamed to changePantsColor for consistency with change[Eye|Hair|Shoe]Color. visibleQuestCount Replaced by hasVisibleQuests. Flooring GetFloorPathLookup Use Game1.floorPathData instead. Forest log Moved into Forest.resourceClumps. Game1 bigCraftableInformation Overhauled into Game1.bigCraftableData. clothingInformation Overhauled into Game1.shirtData and Game1.pantsData. objectInformation Overhauled into Game1.objectData. GameLocation getCharacters Removed; use the characters field instead. isTileOccupied
isTileOccupiedForPlacement
isTileOccupiedIgnoreFloors
isTileLocationOpenIgnoreFrontLayers
isTileLocationTotallyClearAndPlaceable
isTileLocationTotallyClearAndPlaceableIgnoreFloorsRemoved. The collision logic has been significantly rewritten and uses a new set of methods (mainly isTilePassable, IsTileOccupiedBy, and CanItemBePlacedHere). Mods should ideally be updated to use the new methods. Here's a drop-in set of extension methods which re-add the older methods. This lets you temporarily fix code until you can update it properly, but depending on these isn't recommended since they won't be maintained in future versions.
expand for non-recommended code public static class GameLocationExtensions { public static bool isTileOccupiedForPlacement(this GameLocation location, Vector2 tileLocation, Object toPlace = null) { return location.CanItemBePlacedHere(tileLocation, toPlace != null && toPlace.isPassable()); } public static bool isTileOccupied(this GameLocation location, Vector2 tileLocation, string characterToIgnore = "", bool ignoreAllCharacters = false) { CollisionMask mask = ignoreAllCharacters ? CollisionMask.All & ~CollisionMask.Characters & ~CollisionMask.Farmers : CollisionMask.All; return location.IsTileOccupiedBy(tileLocation, mask); } public static bool isTileOccupiedIgnoreFloors(this GameLocation location, Vector2 tileLocation, string characterToIgnore = "") { return location.IsTileOccupiedBy(tileLocation, CollisionMask.Buildings | CollisionMask.Furniture | CollisionMask.Objects | CollisionMask.Characters | CollisionMask.TerrainFeatures, ignorePassables: CollisionMask.Flooring); } public static bool isTileLocationOpenIgnoreFrontLayers(this GameLocation location, Location tile) { return location.map.RequireLayer("Buildings").Tiles[tile.X, tile.Y] == null && !location.isWaterTile(tile.X, tile.Y); } public static bool isTileLocationTotallyClearAndPlaceable(this GameLocation location, int x, int y) { return location.isTileLocationTotallyClearAndPlaceable(new Vector2(x, y)); } public static bool isTileLocationTotallyClearAndPlaceableIgnoreFloors(this GameLocation location, Vector2 v) { return location.isTileOnMap(v) && !location.isTileOccupiedIgnoreFloors(v) && location.isTilePassable(new Location((int)v.X, (int)v.Y), Game1.viewport) && location.isTilePlaceable(v); } public static bool isTileLocationTotallyClearAndPlaceable(this GameLocation location, Vector2 v) { Vector2 pixel = new Vector2((v.X * Game1.tileSize) + Game1.tileSize / 2, (v.Y * Game1.tileSize) + Game1.tileSize / 2); foreach (Furniture f in location.furniture) { if (f.furniture_type != Furniture.rug && !f.isPassable() && f.GetBoundingBox().Contains((int)pixel.X, (int)pixel.Y) && !f.AllowPlacementOnThisTile((int)v.X, (int)v.Y)) return false; } return location.isTileOnMap(v) && !location.isTileOccupied(v) && location.isTilePassable(new Location((int)v.X, (int)v.Y), Game1.viewport) && location.isTilePlaceable(v); } }
GiantCrop which Replaced by itemId. Item SanitizeContextTag Replaced by ItemContextTagManager.SanitizeContextTag. LocalizedContentManager LanguageCodeString Now static. LocationContextData Name Removed; use its dictionary key in Game1.locationContextData instead. NetFields AddFields Removed; use AddField instead. For example: // old code NetFields.AddFields(textureName, spriteWidth, spriteHeight); // new code NetFields .AddField(textureName) .AddField(spriteWidth) .AddField(spriteHeight);
Note that the second argument (name) should usually be omitted, since it'll be auto-populated from the value passed to the first argument.
NPC homeRegion Removed; use npc.GetData()?.HomeRegion instead. Change 0 to "Other" or NPC.region_other, 1 to "Desert" or NPC.region_desert, and 2 to "Town" or NPC.region_town. isBirthday Remove the arguments, like npc.isBirthday(Game1.currentSeason, Game1.dayOfMonth)
→npc.isBirthday()
.populateRoutesFromLocationToLocationList Replaced by WarpPathfindingCache.PopulateCache. Schedule No longer assignable, use one of the TryLoadSchedule overloads instead. Object isPotentialBasicShippedCategory The second argument should now be an integer (like -75 or Object.VegetableCategory) instead of a string (like "-75"). Utility doesItemWithThisIndexExistAnywhere Replace with Utility.doesItemExistAnywhere, which takes a string item ID. For example: Utility.doesItemWithThisIndexExistAnywhere(128)
→Utility.doesItemExistAnywhere("(O)128")
;Utility.doesItemWithThisIndexExistAnywhere(128, true)
→Utility.doesItemExistAnywhere("(BC)128")
.
ForAllLocations
iterateAllCrops
iterateAllItemsRemoved; use the equivalent Utility.ForEach* methods instead. GetHorseWarpRestrictionsForFarmer This now returns a flag enum instead of a list of integer values. The equivalent values are 1 → NoOwnedHorse, 2 → Indoors, 3 → NoRoom, and 4 → InUse. For example:
// old code bool inUse = Utility.GetHorseWarpRestrictionsForFarmer(player).Any(p => p == 4); // new code bool inUse = Utility.GetHorseWarpRestrictionsForFarmer(player).HasFlag(Utility.HorseWarpRestrictions.InUse);
Or to check if no restrictions apply:
bool canSummon = Utility.GetHorseWarpRestrictionsForFarmer(player) == Utility.HorseWarpRestrictions.None;
C# mods can patch Utility.GetHorseWarpErrorMessage if they need to add an error message for a custom restriction value.
getTodaysBirthdayNPC Remove the arguments, like Utility.getTodaysBirthdayNPC(Game1.currentSeason, Game1.dayOfMonth)
→Utility.getTodaysBirthdayNPC()
.getPooledList
returnPooledListThe game no longer uses a list pool. In most cases you should use the Utility.ForEach* methods instead, which don't need it. numObelisksOnFarm Renamed to GetObeliskTypesBuilt, which searches all locations. numSilos Removed. If you're using this to calculate hay capacity, it's a bit more complicated in 1.6 since hay storage can be enabled for custom buildings and building construction can be enabled for any location. To get capacity for the current location, use Game1.currentLocation.GetHayCapacity() instead. To get total hay capacity in the world, use Utility.ForEachLocation to call it on every location.
If you actually need the number of silos, use location.getNumberBuildingsConstructed("Silo") (one location) or Game1.GetNumberBuildingsConstructed("Silo") (all locations).
removeThisCharacterFromAllLocations Removed; use Game1.removeCharacterFromItsLocation instead. ShopMenu storeContext Replaced by ShopId. Check for obsolete code
Perform a full rebuild of your mod (in Visual Studio, click Build > Rebuild Solution), then check the Error List pane for any warnings like "'X' is obsolete". Anything from the vanilla game code which is marked obsolete won't work anymore and is only kept for save migrations. Usually the warning will include an explanation of what you should use instead.
Breaking changes for content packs
This section only describes how this update may break existing mods. See the what's new sections above for more info, including new functionality mods can use.
Standardized ID fields
Stardew Valley 1.6 adds an Id field to these assets. For Content Patcher content packs, these replace the previous synthetic ID:
asset old key new key migration steps Data/ConcessionTastes
Data/MovieReactions
Data/RandomBundles (area)
Data/RandomBundles (bundle)Name
NPCName
AreaName
noneId None. The Id field is set automatically to the same value (or Name for bundles), so there's no change for content packs. Omit the new field when creating a new entry. Data/FishPondData
Data/RandomBundles (bundle set)RequiredTags
noneId Use the new Id field to target an entry, and add it when creating a new entry. Required. Data/TailoringRecipes FirstItemTags and SecondItemTags Id Use the new Id field to target an entry, and add it when creating a new entry. Defaults to the CraftedItemIds (comma-delimited) or CraftedItemId value if omitted, but there's a high chance of conflicts so mods should always specify a unique ID. For example, let's say you have a patch like this using Content Patcher:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/TailorRecipes", "Entries": { "item_cloth|item_pufferchick": { "FirstItemTags": [ "item_cloth" ], "SecondItemTags": [ "item_pufferchick" ], "CraftedItemId": "(S)1260" } } } ] }
When updating to Stardew Valley 1.6, replace the synthetic ID (item_cloth|item_pufferchick) with a real one:
- To edit an existing entry, unpack the asset and get its new Id value.
- To add a custom entry, use a globally unique ID prefixed with your mod ID. This should only have alphanumeric, underscore, and dot characters so it's safe to use in delimited fields, file names, etc. The recommended format is ExampleAuthor.ModId_EntryName.
For example:
{ "Format": "2.3.0", "Changes": [ { "Action": "EditData", "Target": "Data/TailorRecipes", "Entries": { "ExampleAuthor.ModId_RainCoatFromPufferchick": { "Id": "ExampleAuthor.ModId_RainCoatFromPufferchick", // need to specify ID again when creating it "FirstItemTags": [ "item_cloth" ], "SecondItemTags": [ "item_pufferchick" ], "CraftedItemId": "(S)1260" } } } ] }
Event ID changes
- See also: string event IDs in what's new.
Events now have unique string IDs.
When creating an event:
- New events should use a globally unique ID in the form Your.ModId_EventName. Existing events should be fine as-is, but it may be worth migrating them to avoid future conflicts.
- Every non-fork event must have a precondition in its key (even if it's empty). For example, change
"Your.ModId_EventName": "..."
to"Your.ModId_EventName/": "..."
. This is needed for the game to distinguish between events and fork scripts."Example.ModId_EventName/": "...", // event: loaded automatically by the game "SomeFork": "..." // event fork: ignored unless it's loaded through an event script
Monster eradication goal flag changes
- See also: Custom monster eradication goals.
The game now tracks Adventurer's Guild monster eradication goal completion by the goal ID, instead of the produced item. You'll need to replace these mail flags if you check them:
old flag new flag Gil_Slime Charmer Ring Gil_Slimes Gil_Savage Ring Gil_Shadows Gil_Vampire Ring Gil_Bats Gil_Skeleton Mask Gil_Skeletons Gil_Insect Head Gil_Insects Gil_Hard Hat Gil_Duggy Gil_Burglar's Ring Gil_DustSpirits Gil_Crabshell Ring Gil_Crabs Gil_Arcane Hat Gil_Mummies Gil_Knight's Helmet Gil_Dinos Gil_Napalm Ring Gil_Serpents Gil_Telephone Gil_FlameSpirits XNB impact
Here's a summary of the XNB files which changed in Stardew Valley 1.6. This doesn't include new files (since they won't impact existing mods), or changes in non-English files.
Shorthand:
- 'broken' means removing new content or potentially important changes, or potentially causing significant display bugs. This is a broad category — the game may work fine without it or crash, depending how it uses that specific content.
- 'mostly unaffected' means mods will only be affected if they edit specific entries or fields.
- Blank means no expected impact for the vast majority of mods.
XNB mods are disproportionately affected since (a) they replace the entire file and (b) they're loaded through the MonoGame content pipeline which is less tolerant of format changes.
content file changes XNB Content Patcher Buildings/houses fixed missing pixels ✘ will remove changes ✓ mostly unaffected Characters/Dialogue/Abigail
Characters/Dialogue/Alex
Characters/Dialogue/Caroline
Characters/Dialogue/Demetriusfixed typos ✘ will remove changes ✓ mostly unaffected Characters/Dialogue/Emily fixed typos, updated %revealtaste format (backwards-compatible) ✘ will remove changes ✓ mostly unaffected Characters/Dialogue/Gus
Characters/Dialogue/Haley
Characters/Dialogue/Jodifixed typos ✘ will remove changes ✓ mostly unaffected Characters/Dialogue/Lewis updated %revealtaste format (backwards-compatible) ✘ will remove changes ✓ mostly unaffected Characters/Dialogue/Linus
Characters/Dialogue/MarriageDialogueAbigail
Characters/Dialogue/MarriageDialogueElliottfixed typos ✘ will remove changes ✓ mostly unaffected Characters/Dialogue/MarriageDialogueEmily changed spring_Maru key to spring_Emily, fixed typos ✘ will remove changes ✓ mostly unaffected Characters/Dialogue/MarriageDialogueMaru
Characters/Dialogue/MarriageDialoguePenny
Characters/Dialogue/MarriageDialogueSam
Characters/Dialogue/Maru
Characters/Dialogue/Pierre
Characters/Dialogue/Robin
Characters/Dialogue/Sam
Characters/Dialogue/Sebastianfixed typos ✘ will remove changes ✓ mostly unaffected Characters/schedules/Elliott fixed order of Fri_6 and Fri entries ✘ will remove changes Characters/schedules/Lewis fixed winter_Sun schedule ✘ will remove changes Characters/schedules/Maru fixed summer_Mon and summer_Sun schedules ✘ will remove changes Characters/schedules/Penny fixed summer_Sun schedule ✘ will remove changes Characters/shirts
Characters/WeddingOutfitsasset removed (they were unused) Data/AquariumFish changed key type, added hat position for Sea Urchin ✘ broken Data/BigCraftablesInformation asset removed (replaced by Data/BigCraftables: migrated to data model format, added new features, changed key type) ✘ broken ✘ likely broken Data/Blueprints asset removed (replaced by Data/Buildings) ✘ broken ✘ broken Data/Boots changed key type, added display name ✘ broken ✘ likely broken Data/Bundles can no longer omit empty fields before display name, added display name field in English, removed meat items in animal bundle ✘ broken ✘ likely broken Data/ClothingInformation asset removed (replaced by Data/Pants and Data/Shirts) ✘ broken ✘ likely broken Data/ConcessionTastes added new required fields (Texture and SpriteIndex), added automatic ID field ✘ broken ✓ mostly unaffected
(✘ broken if they add new concessions)Data/CookingRecipes no longer has per-language versions, removed display names (now default to item name) ✘ will remove changes ✓ mostly unaffected Data/CraftingRecipes no longer has per-language versions, added default unlock condition, removed display names (now default to item name), fixed typo in Cookout Kit entry ✘ broken ✓ mostly unaffected Data/Crops completely overhauled ✘ broken ✘ broken Data/Events/Farm updated pet event to support custom pet types ✘ broken ✓ mostly unaffected Data/Events/FishShop fixed typos ✘ will remove changes ✓ mostly unaffected Data/Events/Forest fixed typos, updated Jas faceDirection command for sewer event ✘ will remove changes ✓ mostly unaffected Data/Events/IslandHut updated how Leo's name is translated ✘ will remove changes ✓ mostly unaffected Data/Events/IslandNorth updated quote format ✘ broken ✓ mostly unaffected
(✘ likely broken if they edit the 6497421 event)Data/Events/IslandSouth changed event music field from blank to none (backwards-compatible) Data/Events/LeahHouse fixed move command format in Leah's 2-heart event ✘ broken Data/Events/Mountain fixed broken dialogue in Maru's 14-heart event, fixed typos ✘ will remove changes ✓ mostly unaffected Data/Events/Saloon
Data/Events/SebastianRoomfixed typos ✘ will remove changes ✓ mostly unaffected Data/Events/Town fixed warp command format in community center completed event, fixed typos ✘ broken ✓ mostly unaffected Data/FarmAnimals completely overhauled ✘ broken Data/Festivals/fall27 removed shop field (moved into Data/Shops) Data/Festivals/spring13 migrated to new warpFarmers command, removed shop field (moved into Data/Shops), fixed typos ✘ broken ✓ mostly unaffected
(✘ broken if they edit event script fields)Data/Festivals/spring24
Data/Festivals/summer11
Data/Festivals/summer28
Data/Festivals/winter8migrated to new warpFarmers command, removed shop field (moved into Data/Shops) ✘ broken ✓ mostly unaffected
(✘ broken if they edit event script fields)Data/Festivals/winter25 removed shop field (moved into Data/Shops) Data/Fish no longer has per-language versions, changed key type, field 13 now refers to whether fish can be tutorial catch ✘ broken ✘ likely broken Data/FishPondData added required Id field, added optional Precedence field, changed ItemId field type, moved fallback entries to bottom ✘ broken ✘ likely broken Data/fruitTrees completely overhauled ✘ broken ✘ broken Data/Furniture changed key type, can no longer omit empty fields before display name, added display name field in English ✘ broken ✘ likely broken Data/hats changed key type, can no longer omit empty fields before display name, added display name field in English ✘ broken ✘ likely broken Data/Locations completely overhauled ✘ broken Data/mail migrated to %item id (backwards-compatible), removed unused tax entries, fixed typos ✘ will remove changes ✓ mostly unaffected Data/Monsters renamed Dust Spirit to Dust Sprite ✘ will remove changes ✓ mostly unaffected Data/Movies added optional CustomFields and Textures fields ✘ broken Data/MoviesReactions added automatic ID field, fixed typo ✘ broken ✓ mostly unaffected Data/NPCDispositions asset removed (replaced by Data/Characters) ✘ broken ✘ broken Data/ObjectContextTags asset removed (replaced by ContextTags field in Data/BigCraftables and Data/Objects) ✘ broken ✘ broken Data/ObjectInformation asset removed (replaced by Data/Objects: migrated to data model format, added new features, added new entries, adjusted litter items, changed key type, fixed typos) ✘ broken ✘ broken Data/PainData fixed trailing slash in Deluxe Barn entry Data/Quests changed item fields to use item IDs (backwards-compatible), changed key type to string, fixed typo ✘ broken ✓ mostly unaffected Data/RandomBundles add optional ID field ✘ broken ✓ mostly unaffected Data/SecretNotes updated %revealtaste format (backwards-compatible) ✘ will remove changes ✓ mostly unaffected Data/SpecialOrders changed type of Repeatable and Duration fields, added optional CustomFields and Conditions fields ✘ broken Data/TailoringRecipes changed to string item IDs (backwards-compatible), added optional ID and CraftedItemIdFeminine fields,
adjusted recipes for gender-variant shirts, renamed *ID to *Id✘ broken ✓ mostly unaffected
(MoveEntries may break, but fallback entries are now
checked last automatically)Data/TV/CookingChannel
Data/TV/TipChannelfixed typos ✘ will remove changes ✓ mostly unaffected Data/weapons completely overhauled ✘ broken ✘ likely broken Effects/BrightWhite asset removed LooseSprites/Cursors new sprites in empty area, moved mailbox to Buildings/Mailbox ✘ broken ✓ mostly unaffected LooseSprites/Cursors2 new sprite in empty area ✘ broken Maps/AnimalShop removed unused pathfinding tiles Maps/ArchaeologyHouse removed unused pathfinding tiles Maps/Barn
Maps/Barn2removed unused map properties Maps/Barn3 added AutoFeed map property, removed unused map properties ✘ broken Maps/BathHouse_Entry
Maps/BathHouse_MensLockerremoved unused pathfinding tiles Maps/BathHouse_Pool removed unused map & tile properties, removed unused pathfinding tiles Maps/BathHouse_WomensLocker removed unused pathfinding tiles Maps/Beach removed unused map properties, removed unused pathfinding tiles Maps/Beach-Jellies
Maps/Beach-Luau
Maps/Beach-NightMarketupdated for festival shops now in Data/Shops, removed unused map/tile properties, removed unused pathfinding tiles ✘ broken Maps/Blacksmith removed unused pathfinding tiles Maps/BusStop removed unused map/tile properties, removed unused pathfinding tiles Maps/Cabin
Maps/Cabin1
Maps/Cabin1_marriage
Maps/Cabin2
Maps/Cabin2_marriageremoved assets (they were unused) Maps/Caldera removed unused map property Maps/Club added LocationContext map property ✘ broken Maps/Coop
Maps/Coop2removed unused map properties Maps/Coop3 removed unused map properties, added AutoFeed map property ✘ broken Maps/Desert added LocationContext map property, removed unused map/tile properties, removed unused pathfinding tiles ✘ broken Maps/ElliottHouse removed unused pathfinding tiles Maps/Farm
Maps/Farm_Combat
Maps/Farm_Fishing
Maps/Farm_Foraging
Maps/Farm_FourCorners
Maps/Farm_Island
Maps/Farm_Mining- added new tilesheet;
- added PetBowlLocation map property (for Maps/Four_Corners and Farm/Island only);
- significant tile & tile property changes;
- removed farmhouse + pet bowl areas (now moveable);
- removed unused map/tile properties;
✘ broken ✓ mostly unaffected Maps/Farm_Greenhouse_Dirt
Maps/Farm_Greenhouse_Dirt_FourCornersremoved unused map properties Maps/FarmHouse removed unused map properties Maps/FarmHouse_Bedroom_Normal
Maps/FarmHouse_Bedroom_Open
Maps/FarmHouse_Cellar
Maps/FarmHouse_ChildBed_0
Maps/FarmHouse_ChildBed_1
Maps/FarmHouse_CornerRoom_Add
Maps/FarmHouse_CornerRoom_Remove
Maps/FarmHouse_SouthernRoom_Add
Maps/FarmHouse_SouthernRoom_Remove
Maps/FarmHouse1
Maps/FarmHouse1_marriage
Maps/FarmHouse2
Maps/FarmHouse2_marriageremoved unused map properties Maps/FishShop fixed broken DayTiles and NightTiles values, removed unused pathfinding tiles ✘ will remove changes Maps/Forest removed unused map/tile properties, removed unused pathfinding tiles Maps/Forest-FlowerFestival updated for festival shops now in Data/Shops, removed unused map properties ✘ broken Maps/Forest-IceFestival updated for festival shops now in Data/Shops, fixed warp positions, removed unused map/tile properties, removed unused pathfinding tiles ✘ broken Maps/Forest-SewerClean removed unused map/tile properties Maps/HaleyHouse
Maps/HarveyRoomremoved unused pathfinding tiles Maps/Hospital removed unused pathfinding tiles Maps/Island_Bridge_Broken
Maps/Island_Bridge_Repaired
Maps/Island_House_Caveremoved unused map properties Maps/Island_N update walnut bush tile so it still works in 1.6, removed unused tile property ✘ broken Maps/Island_N_Trader
Maps/Island_Secret
Maps/Island_Wremoved unused tile property Maps/IslandFarmHouse removed unused tile properties Maps/JojaMart removed unused pathfinding tiles Maps/JoshHouse removed unused pathfinding tiles Maps/LeahHouse removed unused pathfinding tiles Maps/ManorHouse removed unused pathfinding tiles Maps/MarnieBarn
Maps/Mineremoved unused map properties Maps/Mountain removed unused map properties, removed unused pathfinding tiles Maps/Mountain-BridgeFixed
Maps/Mountain_Shortcutsremoved unused map properties Maps/MovieTheaterScreen updated for tilesheet changes ✘ broken visuals (e.g. missing chairs) ✓ mostly unaffected
(✘ broken visuals if they edit the affected tiles)Maps/MovieTheaterScreen_TileSheet improved light cone, moved chair sprite to make room for new light cone ✘ broken visuals (e.g. missing chairs) ✓ mostly unaffected
(✘ broken visuals if they edit the affected sprites)Maps/paths added icon for custom wild tree spawn, removed unused pathfinding tiles Maps/qiNutRoom_tilesheet_0 removed asset (unused) Maps/Railroad removed unused map property, removed unused pathfinding tiles Maps/Saloon removed unused pathfinding tiles Maps/SamHouse removed unused pathfinding tiles Maps/SandyHouse added LocationContext map property ✘ broken Maps/ScienceHouse removed unused pathfinding tiles Maps/SebastianRoom removed unused pathfinding tiles Maps/SeedShop removed unused tile properties, removed unused pathfinding tiles Maps/Shed added FloorIDs and WallIDs map properties ✘ broken Maps/SkullCave added LocationContext map property ✘ broken Maps/SlimeHutch removed unused tile property Maps/spousePatios removed unused map properties Maps/spring_outdoorsTileSheet
Maps/summer_outdoorsTileSheet
Maps/fall_outdoorsTileSheet
Maps/winter_outdoorsTileSheetPet bowl moved to Buildings/Pet Bowl. ✓ mostly unaffected ✓ mostly unaffected Maps/Submarine removed unused tile property Maps/Tent removed unused pathfinding tiles Maps/Town removed unused map properties, changed to new garbage can IDs (backwards-compatible), removed unused pathfinding tiles Maps/Town-Christmas updated for festival shops now in Data/Shops, removed unused map properties, removed unused pathfinding tiles ✘ broken ✓ mostly unaffected Maps/Town-DogHouse removed unused map properties Maps/Town-EggFestival fixed Elliott appearing twice during egg hunt, updated for festival shops now in Data/Shops, removed unused map properties ✘ broken ✓ mostly unaffected Maps/Town-Fair removed unused map properties Maps/Town-Halloween updated for festival shops now in Data/Shops, removed unused map properties, removed unused pathfinding tiles ✘ broken ✓ mostly unaffected Maps/Town-Theater
Maps/Town-TheaterCC
Maps/Town-TrashGoneremoved unused map properties Maps/Trailer removed unused tile property, removed unused pathfinding tiles Maps/Trailer_big removed unused pathfinding tiles Maps/Tunnel removed unused map property Maps/WizardHouse removed unused pathfinding tiles Maps/WizardHouseBasement removed unused map property Maps/Woods removed unused tile property Strings/Buildings
Strings/Charactersadded new entries ✘ broken Strings/credits updated credit line ✘ will remove changes ✓ mostly unaffected Strings/FarmAnimals added new entries ✘ broken Strings/Locations replaced bus price with placeholder, updated how Professor Snail's name is translated, removed unused entries, fixed typos ✘ broken ✓ mostly unaffected Strings/NPCNames added new entries ✘ broken Strings/Objects
Strings/schedules/Carolinefixed typos ✘ will remove changes ✓ mostly unaffected Strings/SpecialOrderStrings renamed Dust Spirit to Dust Sprite ✘ will remove changes ✓ mostly unaffected Strings/StringsFromCSFiles added new entries, removed unused entries, fixed typos ✘ broken ✓ mostly unaffected Strings/StringsFromMaps fixed typos ✘ will remove changes Strings/UI added new entries, fixed typos ✘ broken ✓ mostly unaffected Vanilla release notes
⚠These are unofficial release notes for the 1.6 mod author alpha.
The new content announced by ConcernedApe hasn't been revealed yet and isn't listed below.This is a draft for the Version History section when 1.6 is released. Feel free to edit or suggest anything that was missed.
1.6.0
Stardew Valley 1.6.0 was released to the Steam beta branch on XX XX 20XX, and released on XX XXXX 20XX.- New features
-
- The world map now shows your actual position within the world in real-time (instead of showing you at a fixed point for each location). In multiplayer, you'll see other players' position in real-time too. This currently doesn't apply in Cindersap Forest or Pelican Town, since their drawn map is too different from the real location.
- The farmhouse and pet bowl can now be moved through Robin's menu.
- The farm computer can now be used anywhere to see a summary of that location, instead of only the farm.
- The mini-jukebox can now be used on the Ginger Island farm.
- Balance changes
-
- You can no longer lose the Golden Scythe, Infinity weapons, or tools when dying.
- Added grace jumps in Junimo Kart: when you run off the track, you can still jump for a short time to recover.
- Increased the shaving enchantment's effect on giant crops.
Each giant crop now has a 60% chance of dropping an extra six crops while the shaving enchantment is equipped, spread across the number of hits needed to break it. For example, a base axe which breaks the giant crop in three hits gets three 20% chances of dropping 2 crops. - The mushroom cave now provides mushrooms every second day. It was unintentionally changed to daily in Stardew Valley 1.5.
- Randomization no longer produces simple repeating patterns in many cases (e.g. clay farming, mushroom level prediction, crab pot fish offset, etc).
You can enable "Use Legacy Randomization" in the advanced save options to use the old randomization, though some specific patterns may still change due to the underlying changes. That option is mainly intended for speedrunners; most players should keep it disabled for the intended experience.
- Quality of life changes
-
- Shops now have a slight delay before you can buy/sell items, to help avoid double-clicks doing it accidentally.
- Planting cactus seeds on the farm now fails with a message, instead of the seeds dying overnight.
- Marnie's animal menu now shows prices in the tooltip, in case the tooltip covers the price display.
- Holding a tea sapling or seed over a garden pot now shows the green/red placement tile.
- The museum reward menu now prevents picking up a reward that won't fit in your inventory.
- The museum reward menu now lets you exit while holding a reward. It'll be added to your inventory if possible, otherwise it'll drop at your feet.
- If an item menu exits while you're holding an item, the item is now always retrieved. (Previously only some item menus like chests would do it.)
- If a default farm building (like the greenhouse) is somehow removed, it'll now be rebuilt next time you load the save.
- You can no longer pick up rugs if there's something on it.
- Positional sounds now fade with distance when off-screen, instead of cutting off abruptly.
- Made more sounds positional (mainly player and tool sounds).
- Deleting a save on PC is now much faster.
- Significantly reduced save loading time when there are many custom locations.
- Performance improvements.
- Other changes
-
- Gender-specific clothing variants can now be worn by any gender.
- After reaching six hearts with some NPCs, they won't visit their rival love interest anymore. This affects Alex visiting Haley, Elliott visiting Leah, and Haley visiting Alex.
- The about page now shows the build number.
- The about page no longer hides the version if a tip message is shown.
- The Ginger Island shrine item pedestals are now normal items. Modded players can spawn them to display items decoratively (though they're not obtainable in vanilla currently).
- Fixed some NPC schedules not being applied:
- Fixes for gameplay
-
- Fixed issues with buffs:
- Fixed a range of bugs like attribute drift and double-debuff.
- Fixed food/drink buffs discarded if they have a balanced total of effects (e.g. +2 attack and -2 speed).
- Fixed negative custom buffs shown with a double-negative (e.g. "--2 speed").
- Fixed Squid Ink Ravioli buff not remaining active if another food buff is added later (although the buff icon was still shown).
- Fixed Squid Ink Ravioli not resetting the buff duration when you eat another one, unlike other food buffs.
- Fixed Squid Ink Ravioli description having an extra blank line.
- Fixed Burnt not showing the -3 Attack effect.
- Fixed unable to leave the Festival of Ice until it ends.
- Fixed player stuck in swimsuit if they collapse from damage while wearing it.
- Fixed gates popping off when closing them while the player overlaps the tile.
- Fixed broken event if the player is defeated in the mines and their name contains a slash.
- Fixed fishing crash if a treasure chest appears while the player has a large number of stacked fishing buffs.
- Fixed issue where breaking a bee house containing honey would drop a generic "Honey" item, instead of the flavored honey it would produce when harvested.
- Fixed issue where using the rain totem during a storm would make the next day stormy too, instead of rainy.
- Fixed issue where you could clear a forest-themed mine level without finding a ladder.
- Fixed magic bait disabling some fish area checks (e.g. so you could catch river fish in the forest pond).
- Fixed random seeds on Ginger Island being based on the valley's season.
- Fixed dropped tools not recovered if they're inside a constructed building.
- Fixed potted tea bushes planted in town not being harvestable.
- Fixed wedding rings being giftable to NPCs.
- Fixed exploit where you could keep temporary items like Qi Fruit by selling them to Pierre and buying them back later.
- Fixed issues with buffs:
- Fixes for NPC dialogue
-
- Many NPCs have their own dialogue for accepting a movie invitation, but only in English. This now works in other languages too.
- Fixed some dialogues that were never shown in-game.
Specifically a line in Maru's 14-heart event, three dialogues from Sam related to Kent, two randomized dialogues when an NPC buys an item you sold to a shop, and two speech bubbles from Marnie/Robin when you enter their shop building. - Fixed Lewis not congratulating female farmers after their wedding.
- Fixed Lewis skipping his final dialogue at the Festival of Ice on subsequent player wins.
- Fixed the fortune teller nearly always showing the text for your combat skill, instead of your highest skill.
- Fixed issue where an NPC who bought an iridium-quality item you sold to a shop could show a low-item-quality dialogue for it.
- Fixed monster grave text only shown in English.
- Fixes for visual or cosmetic issues
-
- The submerged fishing bobber is now recolored automatically to match the water.
- Fixed cursor over NPCs sometimes showing a gift icon when they won't accept or react to the held item.
- Fixed quality fertilizer showing a green tile on sprouted crops, even though it can't be placed there.
- Fixed the
!
fish bite icon not shown when fishing in the Stardew Valley Fair and Festival of Ice. - Fixed some in-game error messages not having an error icon.
- Fixed inventory & crafting menus misaligned if you resize the window while they're open.
- Fixed fruit tree leaves not rustling in winter even if they're in a non-seasonal location like the greenhouse.
- Fixed weeds being less varied than intended in summer.
- Fixed intro cutscene position not adjusted when the farmhouse is moved by a mod.
- Fixed cosmetic issues with the title & shipping screens for higher-resolution displays.
- Fixed calendar tooltip when a modded festival and birthday occur on the same day.
- Fixed beds or chests that were hidden for an event not reappearing afterwards.
- Fixed pre-built cabins sometimes placed on top of a bush or log.
- Fixed furniture drawn over sitting players if it has no front texture.
- Fixed the forge preview always showing soul level one for a galaxy soul forge.
- Fixed many things on Ginger Island applying the valley's season or weather (including fiber seeds, seasonal decor, seasonal plants, tea bushes, and tubs o' flowers).
- Fixed advanced save option tooltips being able to extend off-screen, and not shown for some field labels.
- Fixed Elliott appearing twice during the egg hunt.
- Fixed bombs being invisible when placed on the summit.
- Fixes for display text and localization
-
- Spanish prices are now formatted like 15o instead of 15g to match the translated term (oro instead of gold).
- Fixed many issues in dialogue, events, and other display text (including typos, broken tokens, translations that don't match the original, etc).
- Fixed NPC name translations applied to horses/pets that share a name with that NPC.
- Fixed unlocalized text shown for...
- the building paint menu's region names (like "Roof" or "Trim");
- NPC names in some movie theater dialogue;
- Professor Snail's name after his first event;
- Leo's name in his introductory event for some languages;
- fish names for some languages in certain cases;
- the 'Miss' text when an attack misses.
- Fixed random name generator able to produce words similar to certain slurs.
- Fixed dust sprites called dust spirits in Clint's special order and the summit cutscene.
- Fixed Lewis' letter for Feast of the Winter Star saying it starts at 10am instead of 9am.
- Fixed some recipe names not matching the items they produce.
- Fixed the hats added in 1.5 translating their internal name instead of setting the display name in some languages.
- Fixed French formatting times past midnight like "26h" instead of "02h" (e.g. on the fishing TV channel).
- Fixed French and Turkish showing broken dialogues about another NPC's gift tastes.
- Fixed German truncating Professor Snail's name in his intro event.
- Fixed Japanese and Korean formatting buff effects inconsistently.
- Fixed Korean credit line missing in other languages.
- Fixed Russian event for Professor Snail's intro freezing.
- Fixed for multiplayer
-
- Joining multiplayer through a Steam invite will now use the Steam servers directly, instead of the GOG servers. This may improve connection stability in some cases.
- Partly fixed an old Steam username sometimes shown to other players when you join. It's fixed when connecting through a Steam invite, still being investigated in other cases.
- Possibly fixed frequent disconnections for some players.
- Fixed egg festival requiring 12 eggs to win if there are 5+ players. It now applies the four-player requirement to any player count beyond that.
- Fixed farmhands sometimes able to walk out of bounds at festivals.
- Fixed various cases where values weren't correctly synced between players.
- Fixed watered dirt edges not updated for farmhands when they change overnight.
- Fixes for modded players
-
- Monsters no longer spawn at night by default on custom farm types.
- Non-binary NPCs can now pathfind through any gendered route (e.g. men's or women's locker room), instead of defaulting to female routes.
- Fixed crashes when...
- loading a save with unknown locations, an invalid farm type, NPCs with no sprite texture, or null world objects.
- the farm map has no grass spawn tile and you walk through crops or grass.
- the data for an item, animal, tree, etc no longer exists.
- painting a building if its sprite changed to a smaller one since it was last painted.
- playing audio which doesn't exist (it now logs an error and plays a default 'quiet click' sound instead).
- a farmhand warps to a location which doesn't exist locally yet.
- an NPC can't parse its dialogue (it now logs the error and defaults to "..." instead).
- a mini-jukebox has an invalid track selected (it now turns off instead).
- a mini-shipping bin has null items.
- a statue of endless fortune tries to produce a gift for an NPC whose first loved gift is a category or context tag (it now now chooses the first valid gift taste, and falls back to a non-birthday gift if none was found);
- a farm animal warps home in rare cases.
- Fixed calendar support for multiple events on the same day (including multiple weddings, multiple birthdays, birthdays on a festival day, etc).
- Fixed horses in indoor locations or mine/volcano levels unable to return home.
- Fixed event setup not allowing more than 9 players.
- Fixed events not exiting correctly if they crash before the first script command.
- Fixed event errors not logged to the console.
- Fixed potential event crash if a custom NPC name contains 'farmer'.
- Fixed save loading very slowly if it has a broken outdoors location in some cases.
- Fixed some items being unremovable when spawned by players. This affects incubators, mushroom boxes, slime balls, and three unused items (locked doors and alternate wicked statue).
- Other bug fixes
-
- Fixed crashes when...
- taking a screenshot on macOS if the ~/.local folder doesn't exist.
- a farmhand warps just as certain things happen (e.g. pet sounds).
- Fixed able to equip a staircase as pants to obtain trimmed lucky purple shorts.
- Fixed being able to place a yellow couch in a loom.
- Fixed wilderness farm spawning a stone in water.
- Fixed hilltop farm spawning grass inside of stumps.
- Fixed Trash Bear treated as a villager (e.g. it could theoretically be picked for quests).
- Fixed save folder collision if you set the save's name & seed to the same value as an existing save.
- Fixed issue where viewing a letter with multiple pages and positioning the cursor directly above the skip button could cause the next viewed event to be skipped when the A button is pressed to progress text.
- Fixed the lonely stone map tooltip not accessible with a gamepad.
- Fixed the build number not set on Linux/macOS.
- Fixed crashes when...
- Other changes
See also
- Modding wishlist items done in Stardew Valley 1.6 lists a few specialized changes not mentioned on this page.