模组:迁移至游戏本体1.5.5

来自Stardew Valley Wiki
跳到导航 跳到搜索

目录

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

不完整的翻译

本文或部分尚未完全翻译成中文。 欢迎您通过编辑帮助其建设。
最后编辑Shirotsuki于2023-04-04 18:20:11.

此页面介绍了如何更新你的模组以与 Stardew Valley 1.5.5 兼容,并记录了一些更改和新功能

对于 SMAPI MOD

星露谷兼容性分支

星露谷 1.5.5 可在每个操作系统的两个分支中使用(游戏内容完全相同):主分支 是默认安装的选项,和一个可选的“兼容分支”适用于 早期的系统版本,它提供相同的内容,但使用不同的技术:

分支 系统 游戏框架 运行时
主分支 Linux/macOS MonoGame 3.8 64 位 .NET 5
Windows MonoGame 3.8 64 位 .NET 5
兼容分支 Linux/macOS MonoGame 3.5.1 64 位 Mono 4.5
Windows XNA Framework 4.0 32 位 .NET Framework 4.5

但是 此版本的 SMAPI 仅支持游戏的主分支 There are formidable difficulties across all mods in supporting all three variations Steam 用户硬件数据 显示大约 99.69% 的玩家拥有 64 位操作系统,而 32 位系统很多事情都不能做.

64 位 MonoGame 和 .NET 5

Stardew Valley 1.5.5 在所有平台上迁移到 64 位 MonoGame 和 .NET 5。SMAPI 可以自动重写模组,所以它们应该仍然可以工作,但强烈建议为每个 C# mod 发布更新以避免特殊情况。

更新你的 C# 模组的代码:

  1. 启用 64 位 兼容性 如果你没有准备好的话。(除非明确更改项目设置,否则默认情况下模组是 64 位的)
  2. 如果您还没有将 .csproj 文件迁移到新格式:
    1. 更改模组工程的 .csproj 文件:
      <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
          <AssemblyName>程序集名称</AssemblyName>
          <RootNamespace>根命名空间</RootNamespace>
          <Version>版本</Version>
          <TargetFramework>net452</TargetFramework>
        </PropertyGroup>
      
        <ItemGroup>
          <PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="3.3.0" />
        </ItemGroup>
      </Project>
      
    2. 如果模组使用 Harmony,添加 <EnableHarmony>true</EnableHarmony> 到属性组。
    3. 更新 程序集名称根命名空间版本 标签。(You can delete the AssemblyName and RootNamespace tags if they just match the project name.)
    4. 添加你要使用的任何 NuGet 包
    5. 删除Properties/AssemblyInfo.cs文件, packages文件夹, 以及 packages.config 文件 (if present).
  3. Edit your mod's .csproj file, and replace <TargetFramework>net452</TargetFramework> with <TargetFramework>net5.0</TargetFramework>.
  4. Update the mod build package to the prerelease 3.4.0 version.
  5. Exit Visual Studio.
  6. Delete your solution's hidden .vs folder, and every project's bin and obj folders.
  7. Reopen the solution in Visual Studio, click Build > Rebuild Solution, fix any errors, and test the mod in-game.

Specific things to check for:

If you need help, feel free to ask in #making-mods on the Stardew Valley Discord!

Asset name format change

Some background first:

  • An asset name identifies an asset you can load through a content API like Game1.content.Load<T>("asset name"). For example: Characters/Abigail.
  • A file path identifies a physical file on the computer. For example: C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley\Content\Characters\Abigail.xnb.

Stardew Valley 1.5.5 makes that distinction more important, since MonoGame uses Linux-style separators in asset names on all platforms. That means asset names no longer match path conventions on Windows.

You should review all code in your mods that creates/compares paths, check whether it's actually creating/comparing asset names, and if so migrate it to the equivalent methods:

code for file paths code for asset names
PathUtilities.NormalizePath("a/b") PathUtilities.NormalizeAssetName("a/b")
Path.Combine("a", "b") PathUtilities.NormalizeAssetName("a/b")
Path.DirectorySeparatorChar PathUtilities.AssetDirectorySeparator

Consistent game assembly name

Previously the game assembly was Stardew Valley on Windows, and StardewValley on Linux and macOS. The assembly is now named Stardew Valley on all platforms. Most mods shouldn't be affected once you update the mod build package.

Scarecrow changes

You can now patch Object.IsScarecrow() and/or Object.GetRadiusForScarecrow() (or add context tags) to support custom scarecrows or custom ranges.

Horse footstep changes

You can now override the footstep logic for a horse by setting its onFootstepAction field. For example:

Horse horse = ...; // get the horse instance you want to change
horse.onFootstepAction = (string tileType) =>
{
   // play custom audio, etc
};

Content changes

See For Content Patcher packs below, which applies for C# mods too.

For Content Patcher packs

Stardew Valley 1.5.5 has no known breaking changes for content packs. All content packs should work fine once the framework mod that loads them is updated.

Custom farm types

You can now add custom farm types by editing the Data/AdditionalFarms asset. Each entry consists of an object with these fields:

field description
ID A unique ID value. This must be globally unique across all mods, so you should prefix your mod ID (e.g., Example.PineapplesAnywhere/PineappleFarm). You should avoid commas for compatibility with Content Patcher packs checking the {{FarmType}} token. This is not shown in-game.
TooltipStringPath Where to get the translatable farm name and description. This must be a key in the form <asset name>:<key>; for example, Strings/UI:Farm_Description will get it from the Farm_Description entry in the Strings/UI file. The translated text must be in the form "<name>_<description>", like "Pineapple Farm_A farm shaped like a pineapple".
MapName The map asset name relative to the Maps folder. For example, Farm_Pineapple would load Maps/Farm_Pineapple.
IconTexture (optional) The asset name for a 22x20 pixel icon texture, shown on the 'New Game' and co-op join screens.
WorldMapTexture (optional) The asset name for a 131x61 pixel texture that's drawn over the farm area in the in-game world map.
ModData (optional) A string→string dictionary of mod-specific metadata for the farm, which can be accessed in C# code via Game1.GetFarmTypeModData(key).

For example, this Content Patcher pack would create a 'pineapple' farm:

{
    "Format": "1.30.0",
    "Changes": [
        // add farm type
        {
            "Action": "EditData",
            "Target": "Data/AdditionalFarms",
            "Entries": {
                "Pathoschild.PineappleFarm/PineappleFarm": { // for technical reasons, you need to specify the ID here *and* in the "ID" field
                    "ID": "Pathoschild.PineappleFarm/PineappleFarm",
                    "TooltipStringPath": "Strings/UI:Pathoschild_PineappleFarm",
                    "MapName": "Pathoschild_PineappleFarm",
                    "IconTexture": "Mods/Pathoschild.PineappleFarm/Icon",
                    "WorldMapTexture": "Mods/Pathoschild.PineappleFarm/WorldMap"
                }
            }
        },

        // add farm name + description
        {
            "Action": "EditData",
            "Target": "Strings/UI",
            "Entries": {
                "Pathoschild_PineappleFarm": "Pineapple Farm_A farm shaped like a pineapple!" // tip: use {{i18n}} to translate it
            }
        },

        // load map
        {
            "Action": "Load",
            "Target": "Maps/Pathoschild_PineappleFarm",
            "FromFile": "assets/map.tmx"
        },

        // load icon
        {
            "Action": "Load",
            "Target": "Mods/Pathoschild.PineappleFarm/Icon, Mods/Pathoschild.PineappleFarm/WorldMap",
            "FromFile": "assets/{{TargetWithoutPath}}.png"
        }
    ]
}

Custom languages

You can now add custom languages by editing the Data/AdditionalLanguages asset. Each entry consists of an object with these fields:

field description
ID A unique ID value. This is not shown in-game.
LanguageCode The language code for this localization. This should ideally be a ISO 639-1 code. You should avoid commas for compatibility with Content Patcher packs checking the {{Language}} token.
ButtonTexture The asset name for a 174x78 pixel texture containing the button of the language for language selection menu. The top half of the sprite is the default state, while the bottom half is the hover state.
UseLatinFont Whether the language uses the same Latin character font as English. If set to false, you must set the next field.
FontFile (optional) The asset name for the font file to use (if UseLatinFont is false).
FontPixelZoom (optional) A factor by while to multiply the font size.
FontApplyYOffset (optional) Whether to shift the font up by four pixels (multiplied by the FontPixelZoom), to better align languages with larger characters like Chinese and Japanese.
SmallFontLineSpacing (optional) The line spacing value used by smallFont. Defaults to 26.
TimeFormat A string which describes the in-game time format, with tokens replaced by in-game values. For example, [HOURS_12]:[MINUTES] [AM_PM] would show 12:00 PM at noon.

The valid tokens are:

  • [HOURS_12]: hours in 12-hour format, where midnight and noon are both "12".
  • [HOURS_12_0]: hours in 12-hour format, where midnight and noon are both "0".
  • [HOURS_24]: hours in 24-hour format, where midnight is "0" and noon is "12".
  • [HOURS_24_00]: hours in 24-hour format with zero-padding, where midnight is "00" and noon is "12".
  • [MINUTES]: minutes with zero-padding.
  • [AM_PM]: the localized text for "am" or "pm" (taken from Strings\\StringsFromCSFiles:DayTimeMoneyBox.cs.10370 and DayTimeMoneyBox.cs.10371 respectively). The game shows "pm" between noon and 11:59pm inclusively; it shows "am" otherwise.
ClockTimeFormat A string which describes the in-game time format. Equivalent to TimeFormat, but used for the in-game clock.
ClockDateFormat A string which describes the in-game date format as shown in the in-game clock, with tokens replaced by in-game values. For example, [DAY_OF_WEEK]. [DAY_OF_MONTH] would show Mon. 1.

The valid tokens are:

  • [DAY_OF_WEEK]: the abbreviated day of week as returned by Game1.shortDayDisplayNameFromDayOfSeason (like Mon for Monday).
  • [DAY_OF_MONTH]: the numerical day of the month.

For example, this Content Patcher pack would add Esperanto to the game:

{
    "Format": "1.30.0",
    "Changes": [
        // define language
        {
            "Action": "EditData",
            "Target": "Data/AdditionalLanguages",
            "Entries": {
                "Pathoschild.Esperanto": { // for technical reasons, you need to specify the ID here *and* in the "ID" field
                    "ID": "Pathoschild.Esperanto",
                    "LanguageCode": "eo",
                    "ButtonTexture": "Mods/Pathoschild.Esperanto/Button",
                    "UseLatinFont": true,
                    "TimeFormat": "[HOURS_24_00]:[MINUTES]",
                    "ClockTimeFormat": "[HOURS_24_00]:[MINUTES]",
                    "ClockDateFormat": "[DAY_OF_WEEK] [DAY_OF_MONTH]"
                }
            }
        },

        // load button texture
        {
            "Action": "Load",
            "Target": "Mods/Pathoschild.Esperanto/Button",
            "FromFile": "assets/button.png"
        }
    ]
}

Once the language is defined, you can add translations to the game by patching game assets like usual, and use the language code you specified above. For example:

{
    "Action": "EditData",
    "Target": "Strings/StringsFromCSFiles",
    "Entries": {
        "Game1.cs.3043": "Lundo",
        "Game1.cs.3044": "Mardo",
        ...
    },
    "When": {
        "Language": "eo"
    }
}

Custom festival location names

The location name in the festival-started message (e.g., "The Luau has begun on the beach") was previously hardcoded, so it would always show the internal name for non-vanilla festival locations. You can now add a locationDisplayName field in the Data/Festivals/* file to set the display name.

Custom spouse rooms

Adding spouse rooms for custom NPCs is now much easier. You can edit the Data/SpouseRooms asset to add the spouse room info in this format: "<NPC name>": "<map name>/<map index>".

field effect
<NPC name> The internal name of the NPC (i.e., their key in Data/NPCDispositions).
<map name> The asset name of the map in the game's Content/Maps folder. This can be a custom map loaded through Content Patcher's Load action or SMAPI's IAssetLoader API.
<map index> The index of the spouse room within the map file, to allow multiple spouse rooms in the same file. Each spouse room is 6 tiles across by 9 tiles down, starting with index 0 in the top-left corner. You can have any number of rows and columns (the index will wrap at the end of the row), as long as they fit an integer number of spouse rooms.

Map property changes

Stardew Valley 1.5.5 adds several map properties:

valid in map property usage
farm FarmFishLocationOverride <location name> <chance> Adds an alternative location name when catching fish, where the <chance> is a decimal value between 0 (never happens) and 1 (always happens). For example, FarmFishLocationOverride Mountain 0.5 adds a 50% chance of catching mountain fish instead of the normal fish for that location. The location name is case-sensitive, and matches those shown by the Debug Mode mod.
farm FarmHouseFurniture [<furniture ID> <tile X> <tile Y> <rotations>]+ Spawns initial furniture in the farmhouse when creating a new save. If you add multiple furniture to the same tile, the first one will be placed on the ground and the last one will be placed on the first one.
This is also required to enable the FarmHouseWallpaper, FarmHouseFlooring, and FarmHouseStarterSeedsPosition properties. You can enable it without spawning any furniture with FarmHouseFurniture -1 0 0 0.
farm FarmHouseFlooring <flooring id> Sets the initial farmhouse floor to the given ID when creating a new save. These are mapped to the 4x4 tile areas in the Maps/walls_and_floors tilesheet starting at tile index 336 (where index 0 is mapped to the top-left square).
This is only enabled if FarmHouseFurniture is set.
farm FarmHouseWallpaper <wallpaper id> Sets the initial farmhouse wallpaper to the given ID when creating a new save. These are mapped to the 1x4 tile areas in the Maps/walls_and_floors tilesheet starting from the top-left.
This is only enabled if FarmHouseFurniture is set.
farm FarmHouseStarterSeedsPosition <tile X> <tile Y> Sets the tile position in the farmhouse where the seed package is placed when creating a new save.
This is only enabled if FarmHouseFurniture is set.
farm FarmOceanCrabPotOverride T Whether crab pots on the farm should catch ocean fish.
any ForceAllowTreePlanting T Whether to allow planting trees (both wild and fruit) in this location, even if it normally wouldn't be allowed.
any IsFarm T Whether to mark the location as a farm. This only affects generic location/interaction logic which checks the in-code location.IsFarm property; logic hardcoded into the game's Farm class (e.g., farm animals, pets, crows/scarecrows, greenhouse, farm buildings, etc) is still limited to the actual farm.
any IsGreenhouse T Whether to mark the location as a greenhouse.
farm SpawnBeachFarmForage T Whether to randomly spawn beach forage and 补给箱 on the farm (like the vanilla beach farm). Forage and crates will only appear on tiles which have the BeachSpawn T property on the Back layer, are clear for placement, and don't have a tile on the AlwaysFront layer.
farm SpawnForestFarmForage T Whether to randomly spawn forest forage on the farm (like the vanilla forest farm). Forage will only spawn on tiles which have the Type Grass tile property, are clear for placement, and don't have a tile on the AlwaysFront layer.
farm SpawnMountainFarmOreRect <tile X> <tile Y> <tile width> <tile height> The tile area on the farm map where ores should randomly spawn (like the vanilla hilltop farm). Ores will only spawn on tiles which have the Type Dirt tile property and are clear for object placement.

And one new tile property:

layer property effect
Back TouchAction Warp <area> <x> <y> [string prerequisite] Adds a player-only warp on the tile to the specified location name and position. This is exactly equivalent to TouchAction MagicWarp, but without the magic sound/visual effect.

It also changes one tile property:

layer property effect
Back Water Setting the value to I (uppercase i) will make the tile behave like normal water, but won't render the water animation overlay for it.

Non-Krobus roommates

The game's 婚姻 logic previously had hardcoded exceptions to treat 科罗布斯 as a roommate instead. That logic has been reworked so it can be applied to any NPC (including custom NPCs).

Specifically:

  • Items with the "propose_roommate_<NPC name>" context tag will trigger a roommate proposal when given to the named NPC. The NPC name must be lowercase with underscores instead of spaces (e.g., propose_roommate_dwarf).
  • These dialogue keys apply before they move in:
    content file key effect
    Strings/StringsFromCSFiles <NPC name>_EngagedRoommate The NPC's roommate proposal accept dialogue.
    ⚠ Ignored if you don't specify Data/EngagementDialogue:<NPC name>Roommate0.
    For example: A Void Ghost pendant! How did you...?$3#$b#Oh, wow.$7#$b#@... yes, I'll come live with you, if you like. But we have to keep it secret from everyone.#$b#I'll be at your house in a few days... okay?$h
    Strings/Characters MovieInvite_NoTheater The NPC's roommate proposal rejection text when you don't meet the requirements (i.e., min friendship + house upgrade level, and not already having a roommate/spouse). This is the same dialogue used when you can't invite someone to the movies.
    Data/EngagementDialogue <NPC name>Roommate0
    <NPC name>Roommate1
    The NPC's normal dialogue after accepting the proposal, but before moving in. The Roommate0 variant is always used on the day the NPC accepted; on subsequent days the NPC randomly chooses Roommate0 or Roommate1. If the Roommate0 variant isn't defined, the NPC will use the normal <NPC Name>0 and <NPC Name>1 keys. If the Roommate0 variant is defined, Roommate1 must be set too to avoid errors.
    For example: @... I'm afraid we'll have to keep this a secret... Neither my people nor yours would accept us living together.

    And after they move in:

    content file key effect
    Characters/Dialogue/MarriageDialogue<NPC name>Roommate all keys Equivalent to Characters/Dialogue/MarriageDialogue<NPC name>, but only applies if the NPC is a roommate. If the file exists, it completely replaces the spouse version; otherwise the game defaults to the spouse version.
    Characters/Dialogue/MarriageDialogue *Roommate Keys with the Roommate suffix take priority if they exist (only in this file, not the MarriageDialogue<NPC name> files).
    Data/Festivals/* <NPC name>_roommate The NPC's normal dialogue at the festival if they're a roommate. If the key isn't defined, they'll use <NPC name>_spouse instead.

    And for other NPCs:

    content file key effect
    Characters/Dialogue/* *_roommate_* Equivalent to the *_inlaw_* infix in generic dialogue, used if you're a roommate with the NPC. If not defined, the game will fallback to the non-infixed dialogue (it won't use the *_inlaw_* variant).
  • Roommates will sleep in a 单人床 if one is available and unused in the house; otherwise they'll use a double bed like a normal spouse. (Krobus is an exception, since he doesn't sleep in a bed.)
  • Added event preconditions to check whether the local player has a roommate (R) or doesn't have a roommate (Rf). This can be combined with O <NPC name> to check for a specific roommate, like R/O Abigail.

Custom scarecrows

You can now mark any placeable item as a 稻草人 with two new context tags:

context tag effect
crow_scare Sets the item as a placeable scarecrow. If not set, the item is considered a scarecrow if its default name contains the substring arecrow (like before).
crow_scare_radius_<radius> If the item is a scarecrow, sets the radius that it covers. If not set, the scarecrow defaults to 17 if the default name contains the substring Deluxe and 9 otherwise.

Update impact

Stardew Valley 1.5.5 only has technical changes; there are no known changes to the player-visible content. Known changes:

content file changes
Effects/BloomCombine
Effects/BloomExtract
Effects/GaussianBlur
These files were deleted.
Fonts/* The actual font files are unchanged, but the JSON output for some fonts when unpacked by StardewXnbHack is a bit different due to the XNA Framework → MonoGame change.

See also