全站通知:

模组:迁移至游戏本体1.6

阅读

    

2024-10-15更新

    

最新编辑:sizau

阅读:

  

更新日期:2024-10-15

  

最新编辑:sizau

来自StardewValley星露谷物语WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索
页面贡献者 :
sizau

目录

注:原页面的创造者为Pathoschild,其他贡献者请参阅此处


本页面仅面向模组开发者。模组玩家请参见模组:模组兼容性


此页面介绍了如何更新你的模组以与星露谷物语 1.6 兼容,并记录了一些更改和新功能。另见迁移至SMAPI 4.0

Robin building.png
“我这里还有很多事情需要处理。”
— 罗宾

不完整的翻译

本文或部分尚未完全翻译成中文。 欢迎您通过编辑帮助其建设。
最后编辑3546754953775813于2024-10-15 10:46:38.

常见问题解答

该版本有何变化?

1.6版本对游戏代码进行了根本性的修改使模组更加具有扩展性。

这就是“模组启示录”吗?

也许吧。更新对游戏基本部分作出了重大改动,而SMAPI和Content Patcher无法重写所有旧版模组以做出适配。这将会另许多模组无法正常运行,直到它们与游戏的更新适配。不过,就游戏开发者和社区之间的讨论而言,我们一致认为这种短期的麻烦将与修改后带来的长期巨大益处相抵消。

如何更新模组?

本页面的其余部分可能让你无从下手。庆幸的是,其中大部分内容可能与您的模组无关。

以下是让模组适配1.6版本的 “快速入门 ”指南:

C#模组:
  1. 模组构建配置NuGet解析包更新到最新版本。
  2. 在每个.csproj项目文件中,将 <TargetFramework>net5.0</TargetFramework> 更改为 <TargetFramework>net6.0</TargetFramework>
    (提示:如果第二行看起来像 <Project ToolsVersion=... 而非 <Project Sdk="Microsoft.NET.Sdk">,则需要先将其迁移至1.5.5。)
  3. 重建方案。
  4. 修复构建错误。您可以根据需要搜索此页面以获取有关信息。
  5. Review all build warnings (particularly obsolete-code warnings), which may indicate code that broke in 1.6.
  6. Increment your mod version in manifest.json.
    (Some mods may be added to SMAPI's compatibility blacklist due to runtime errors. Incrementing the mod version will fix that if so.)
  7. Test to make sure the mod works.
  8. Skim through breaking changes for C# mods and the table of contents, and check any section that might be relevant to the mod.
For Content Patcher packs:
  1. Follow the Content Patcher migration guide until your content pack has "Format": "2.3.0".
    Do not skip this step! Content Patcher will assume your content pack is pre-1.6 if you don't, which can cause confusing errors if you already updated it.
  2. Review breaking changes for content packs and update the content pack as needed.
For content packs which use another framework:
See the documentation for the framework mod. Often you won't need to update the content pack if the framework mod itself was updated.

架构更新

.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...

Trigger actions

参见位于Modding:Trigger actions的最新文档。本节仅描述1.6的更新内容。

Trigger actions are a new feature which lets content packs perform an action when something happens, with support for a wide range of actions (like sending mail, changing friendship, starting a quest, etc).

For example, it lets you have logic like "When the player arrives in the Farm location, if Leo has moved to the valley, then send a letter and start a conversation topic":

{
    "Trigger": "LocationChanged",
    "Location": "Farm",
    "Condition": "PLAYER_HAS_FLAG Host leoMoved",
    "Actions": [
        "AddMail Current Abigail_LeoMoved Today",
        "AddConversationTopic LeoMoved 5"
    ]
}

Hash set fields

For C# mod authors, the game now uses hash sets for many list fields which expect unique values. That allows much more efficient O(1) read/write, prevents duplicate values, and simplifies common logic.

This affects:

type fields
Farmer achievements
dialogueQuestionsAnswered
eventsSeen
mailForTomorrow
mailReceived
professions
secretNotesSeen
songsHeard
FarmerTeam acceptedSpecialOrderTypes
broadcastedMail
completedSpecialOrders
collectedNutTracker
Game1 worldStateIDs
NetWorldState ActivePassiveFestivals
CheckedGarbage
FoundBuriedNuts
IslandVisitors
LocationsWithBuildings

Usage is very similar, and many list methods like Contains work the same way with hash sets. Here are the main differences:

  • Hash sets aren't ordered. For example, there's no guarantee that the first value when you enumerate it was the earliest one added.
  • Hash sets can't be indexed. For example, you can no longer use list[0] to get the first value. You can still enumerate them or use LINQ methods like set.First(), but in most cases you should use the set methods like Add or Contains instead.

    To remove multiple matching values from the set, you can use RemoveWhere instead:

    // old code
    for (int i = Game1.player.mailReceived.Count - 1; i >= 0; i--)
    {
        if (Game1.player.mailReceived[i].StartsWith("Example.ModId_"))
            Game1.player.mailReceived.RemoveAt(i);
    }
    
    // new code
    Game1.player.mailReceived.RemoveWhere(id => id.StartsWith("Example.ModId_"));
    
  • You no longer need to check before adding a value, since the hash set will ignore duplicates.
  • The Add/Remove/RemoveWhere methods return whether a value was added/removed, which lets you check at the same time. For example:
    if (Game1.player.mailReceived.Add("BackpackTip")) // returns true if it wasn't in the set yet
        Game1.addMailForTomorrow("pierreBackpack");
    

DataLoader

DataLoader is a new C# utility which provides strongly-typed methods to load the game's data assets.

This solves an issue where we often needed fragile code like Game1.content.Load<Dictionary<string, PassiveFestivalData>>("Data\\PassiveFestivals"). With that code, it's easy to accidentally misspell the asset name, use different capitalization (which would break on Linux/macOS), or use the wrong return type. If you did, you likely wouldn't notice until the code actually executed at runtime and threw an exception.

In Stardew Valley 1.6, you can now rewrite that code like DataLoader.PassiveFestivals(Game1.content). That's simpler, you can't use the wrong asset name or type, and it's more future-proof in case the game changes them.

Unique string IDs

参见位于Modding:Common data field types#Unique string ID的最新文档。本节仅描述1.6的更新内容。

Stardew Valley now uses unique string IDs throughout the code to identify data (like events, locations, items, NPCs, etc). For example, Town is the unique ID for the Pelican Town location; no other location can use that ID. The IDs are used for a wide range of purposes, from internal game logic to content pack edits.

For mods, it's strongly recommended to...

  • Use namespaced IDs prefixed with your mod's unique ID for all new content. For example, if your mod ID is Example.PufferchickMod and you're adding a pufferchick plushy, your item ID would look like Example.PufferchickMod_PufferchickPlushy. In a Content Patcher pack, you can use {{ModId}}_PufferchickPlushy to insert your mod ID automatically. This eliminates ID conflicts between mods, and makes it easy (for both troubleshooters and mod code) to identify which mod added a particular content. See the new format docs for the recommended format.
  • Only use alphanumeric (a–z, A–Z, 0–9), underscore (_), and dot (.) characters in string IDs. This is important because they're often used in places where some characters have special meaning (like file names or game state queries).

You can optionally migrate pre-1.6 content to use unique string IDs too, without breaking existing players' saves. This is recommended to reduce mod conflicts and simplify troubleshooting going forward. Here's how to migrate for each data type:

migration steps for pre-1.6 content 
content type how to change IDs
event IDs
item IDs
mail IDs
recipe IDs
song IDs for jukebox
Content Patcher adds a custom trigger action which can migrate IDs everywhere in the save data.

For example, this migrates two crafting recipe IDs:

{
    "Action": "EditData",
    "Target": "Data/TriggerActions",
    "Entries": {
        "{{ModId}}_MigrateToUniqueIds": {
            "Id": "{{ModId}}_MigrateToUniqueIds",
            "Trigger": "DayStarted",
            "Actions": [
                // Note: use double-quotes around an argument if it contains spaces. This example has single-quotes for
                // the action itself, so we don't need to escape the double-quotes inside it.
                'Pathoschild.ContentPatcher_MigrateIds CraftingRecipes "Puffer Plush" {{ModId}}_PufferPlush "Puffer Sofa" {{ModId}}_PufferSofa'
            ],
            "HostOnly": true
        }
    }
}

See the Content Patcher docs for more info about using the trigger action, including restrictions and valid ID types.

location IDs Add the old name to the location's FormerLocationNames field in Data/Locations.
NPC internal names Add the old name to the NPC's FormerCharacterNames field in Data/Characters.
quest and special order IDs Currently there's no safe way to migrate quest and special order IDs, since removing and readding them will reset any progress the player has made on them.

What's new for items

Custom items

参见位于Modding:Items的最新文档。本节仅描述1.6的更新内容。

Overview

Stardew Valley 1.6 makes three major changes to how items work in the game:

  1. 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.

  2. 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)).
  3. 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 A unique string ID for this item which should be globally unique (but may not be for existing vanilla items for backwards compatibility). For example, 128 (vanilla item) or Example.ModId_Watermelon (custom item).
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
  • Ingredients: both supported.
  • Output: set field 2 to the unqualified item ID, and field 3 to one of true (bigcraftable) or false (object).
Data/fruitTrees
  • Fruit: both supported.
  • Sapling: unqualified only.
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.

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

Stardew Valley 1.6 added new ways to compare/construct items, define custom item types, and work with item metadata. Please see Modding:Items for the migrated docs.

Custom big craftables

参见位于Modding:Items#Big craftables的最新文档。本节仅描述1.6的更新内容。

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.

Custom crops

参见位于Modding:Crop data的最新文档。本节仅描述1.6的更新内容。

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.

Custom fences

参见位于Modding:Fences的最新文档。本节仅描述1.6的更新内容。

You can now add or customize fences by editing the Data/Fences asset.

Custom floors (craftable) & paths

参见位于Modding:Floors and Paths的最新文档。本节仅描述1.6的更新内容。

You can now add or customize craftable floors & paths by editing the Data/FloorsAndPaths asset. See the new doc page for formatting information.

Custom machines

参见位于Modding:Machines的最新文档。本节仅描述1.6的更新内容。

You can now add/edit machine logic by editing the Data/Machines asset. This supports the full range of vanilla functionality, including calling custom code define in C# mods.

For C# mods, 1.6 also adds a new MachineDataUtility class and various Object to simplify working with machines in code. These are used by the game code itself to implement the base machine logic.

Custom melee weapons

参见位于Modding:Items#Weapons的最新文档。本节仅描述1.6的更新内容。

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).

Custom movie concessions

参见位于Modding:Movie theater data的最新文档。本节仅描述1.6的更新内容。
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 unique string ID.
  • 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.

Custom museum donations & rewards

参见位于Modding:Museum的最新文档。本节仅描述1.6的更新内容。

You can now add/edit the items which the museum gives back in rewards through the new Data/MuseumRewards data asset.

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

参见位于Modding:Fruit trees的最新文档。本节仅描述1.6的更新内容。

You can now add custom fruit trees by editing the revamped Data/FruitTrees asset.

For C# mods, the fruitsOnTree field (number of fruit on the tree) has been replaced by fruit (list of fruit items).

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> [growth stage on location created] [growth stage on day-update regrowth] 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

参见位于Modding:Items#Objects的最新文档。本节仅描述1.6的更新内容。

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.

Custom pants

参见位于Modding:Items#Pants的最新文档。本节仅描述1.6的更新内容。

You can now create/edit pants by editing the new Data/Pants asset, which replaces Data/clothingInformation.

Custom shirts

参见位于Modding:Items#Shirts的最新文档。本节仅描述1.6的更新内容。

You can now create/edit shirts by editing the new Data/Shirts asset, which replaces Data/clothingInformation.

Custom tools

参见位于Modding:Items#Tools的最新文档。本节仅描述1.6的更新内容。

You can now create/edit tools by editing the new Data/Tools asset. Note that drawing the tool correctly in the world (ie, while the player is trying to use it) probably still needs custom code.

Custom wild trees

参见位于Modding:Wild trees的最新文档。本节仅描述1.6的更新内容。

You can now create/edit wild trees by editing the Data/WildTrees asset.

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> [growth stage on location created] [growth stage on day-update regrowth] 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

参见位于Modding:Recipe data的最新文档。本节仅描述1.6的更新内容。

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

参见位于Modding:Fish data的最新文档。本节仅描述1.6的更新内容。

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.

Context tag changes

参见位于Modding:Items#Context tags的最新文档。本节仅描述1.6的更新内容。

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...
  • campfire flames are drawn over it;
  • if the item is big craftable, light is emitted from its center instead of the top.
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:
  • if HasInput is true;
  • or if any output rules have an ItemPlacedInMachine trigger.
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:
  • if HasOutput is true;
  • or if it has any output rules.

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)
hasItemInInventory(id, count)
hasItemInList(list, id, count)
  • To check an item ID, use items.CountId(id) or Items.ContainsId(id, count).
  • To check Golden Walnuts or Qi Gems, use the Game1.netWorldState.Value.GoldenWalnuts and Farmer.QiGems fields.
  • To check category matches or -777 (seasonal wild seeds), the getItemCount and getItemCountInList still exist.
hasItemInInventoryNamed(name)
hasItemWithNameThatContains(name)
In most cases, you should match items by ID instead (see the previous row).

If you really need to match items by name, you can replace it like this:

// exact name
bool hasMatch = Game1.player.Items.Any(item => item?.Name == name);

// name contains
bool hasMatch = Game1.player.Items.Any(item => item?.Name?.Contains(name) is true);
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) Use items.ReduceId(id, count).
removeItemsFromInventory(id, count)
  • To remove an item by ID, use items.ReduceId(id, count).
  • To deduct Golden Walnuts or Qi Gems, change the Game1.netWorldState.Value.GoldenWalnuts and Farmer.QiGems fields.
Object ConsumeInventoryItem(player, id, count) This was somewhat specialized and shouldn't be called by mod code, but the equivalent would be (Object.autoLoadChest ?? player.items).ReduceId(id, count). See also notes for Farmer.removeItemsFromInventory.
GetTallyOfObject(player, id) This was somewhat specialized and shouldn't be called by mod code, but the equivalent would be (Object.autoLoadChest ?? player.items).CountId(id). See also notes for Farmer.getTallyOfObject.

It implements a new IInventory interface, which lets mods pass their own implementations to code which works on inventories.

Furniture changes

参见位于Modding:Items#Furniture的最新文档。本节仅描述1.6的更新内容。
  • Data/furniture no longer has language variants. Translations were moved into Strings/Furniture.
  • There are a few changes in Data/furniture:
    • Field index 6 is now placement restrictions and field index 7 is now display name. The display name field is no longer omitted in English.
    • Field index 7 (display name) now allows tokenizable strings.
    • Added new fields:
      index field effect
      8 sprite index The sprite index within the spritesheet texture to draw.
      9 texture (Optional) The asset name of the texture to draw. Defaults to TileSheets/furniture.
      10 off limits for random sale (Optional) Whether to prevent this furniture from appearing in randomly generated shop stocks and the furniture catalogue. Default false.
      11 context tags (Optional) A space-delimited list of context tags which apply to this furniture. Default none.

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
      Chest GetItemsForPlayer() Shortcut for chest.GetItemsForPlayer(Game1.player.UniqueMultiplayerID).
      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.)

      isWatered() Get whether the dirt is currently watered.
      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
      SetTempData
      Get 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
      SetHeldObject
      Set 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"));
      
      IsTable() Get whether this furniture is a table.
      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.)
    • Fixed fruit trees forgetting the growth stage set in their constructor when they're updated overnight.

    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 (StardewValley.Object.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 of typeAndCategory.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:
      • Missing recipes that should already be unlocked are now added to the player automatically on save load.
      • Data/Bundles is now loaded later, so content packs can edit it reliably.
      • Chests with fridge: true are now treated as mini-fridges for the cooking menu.
      • Gift boxes can now contain multiple items.
      • Fixed furniture drawn over sitting players if it has no front texture.
      • Fixed tool being upgraded by Clint not affected by recursive item search logic.
      • Fixed tool.getOne() not copying the tool name.
      • Fixed cooking menu constantly creating hovered item if the item/recipe names don't match.