模组:迁移至游戏本体1.5.5
阅读
2024-10-15更新
最新编辑:sizau
阅读:
更新日期:2024-10-15
最新编辑:sizau
←目录
不完整的翻译 本文或部分尚未完全翻译成中文。
欢迎您通过编辑帮助其建设。 |
此页面介绍了如何更新你的模组以与 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# 模组的代码:
- 启用 64 位 兼容性 如果你没有准备好的话。(除非明确更改项目设置,否则默认情况下模组是 64 位的)
- 如果您还没有将 .csproj 文件迁移到新格式:
- 更改模组工程的 .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>
- 如果模组使用 Harmony,添加
<EnableHarmony>true</EnableHarmony>
到属性组。 - 更新 程序集名称、根命名空间、版本 标签。(You can delete the AssemblyName and RootNamespace tags if they just match the project name.)
- 添加你要使用的任何 NuGet 包
- 删除Properties/AssemblyInfo.cs文件, packages文件夹, 以及 packages.config 文件 (if present).
- 更改模组工程的 .csproj 文件:
- Edit your mod's .csproj file, and replace
<TargetFramework>net452</TargetFramework>
with<TargetFramework>net5.0</TargetFramework>
. - Update the mod build package to the prerelease 3.4.0 version.
- Exit Visual Studio.
- 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, fix any errors, and test the mod in-game.
Specific things to check for:
Constants.GameFramework
now always returns MonoGame. Any code which checks for Xna can be removed or rewritten.
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": "2.3.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:
|
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:
|
For example, this Content Patcher pack would add Esperanto to the game:
{
"Format": "2.3.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 |
---|---|
|
The internal name of the NPC (i.e., their key in Data/NPCDispositions). |
|
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. |
|
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>
_EngagedRoommateThe 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?$hStrings/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>
Roommate1The 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>
Roommateall 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>
_roommateThe 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. |