全站通知:

模组:迁移至游戏本体1.6.9

来自星露谷物语维基
跳到导航 跳到搜索

目录

当前页面编写的内容面向模组的开发者。模组玩家请阅读模组:模组兼容性


此页面解释如何升级您的模组以与星露谷物语 1.6.9兼容,并记录一些更改和新功能。另请参阅迁移至游戏本体 1.6

问答

该版本有何变化

星露谷 1.6.9 包括了许多 1.6 更新后的小更改。

这是一次巨变吗

SMAPI 兼容性走势图。星露谷 1.6.9 的发布在图中体现为一个较小的下降。

不是。大部分模组应该不受 1.6.9 变化的影响,且 SMAPI 会自动进行相应的重写。

如何升级您的模组

大多数模组不需要任何更改。下面是一个将模组升级到 1.6.9 的“快速上手”指南:

对于 C# 模组:
  1. 若您尚未迁移到游戏本体 1.6 版本,请先升级到 1.6.0 版本
  2. 重新构建解决方案。
  3. 修复任何构建错误。您可以在此页面中搜索相关信息。
  4. 测试,以确保您的模组工作正常。
  5. 快速浏览下方介绍的更改,并查阅那些可能涉及您的模组的章节。
对于 Content Patcher 内容包
  1. 若您还没有升级,请先按照 Content Patcher migration guide 将您的内容包升级到 "Format": "2.7.0"
    不要跳过这步! 如果您没有更新清单文件,Content Patcher 会假定您的内容包是早于 1.6 版本的,如果您已经升级,这就会导致令人困惑的错误。
  2. 快速浏览下方介绍的更改,并查阅那些可能设计您的模组的章节。
对于使用其他框架的内容包:
参见相应框架模组的文档。如果框架模组自身更新了,您往往不需要升级相应内容包。

针对所有模组的更改

遗失物品商店

完整文档见模组:遗失物品商店。本章节仅对更新的内容作简单的介绍。

1.6.9 在秘密森林中添加了一个隐藏商店,出售您已经解锁但不再拥有的特殊物品。例如,汽水机是从 Joja 超市竣工事件中获得的;如果您丢失了它,它将永远消失。所有物品都以固定的 Gold.png10,000 价格出售。

商店中可能出现的物品列在新的 Data/LostItemsShop 素材中,该素材是包含如下字段的数据模型所组成的列表:

字段 效果
Id 此条目的唯一字符串ID
ItemId 要添加到商店的物品的限定性物品 ID。
RequireMailReceived
RequireEventSeen
将此物品添加到商店的要求。

您可以指定 RequireMailReceived(玩家已收到的信件标识)或 RequireEventSeen(玩家已看到的事件 ID)。如果您同时指定两者,则仅使用RequireMailReceived

添加到商店的物品数量是匹配此字段的玩家数量减去世界中存在的物品数量。例如,如果三个玩家曾经找到过《小船》,但世界上只存在一幅《小船》,则商店将出售两幅《小船》。

对话更改

完整文档见模组:对话。本章节仅对更新的内容作简单的介绍。
  • 1.6.9 添加了几个新的对话键:
    素材 键格式 描述
    Characters/Dialogue/<name> AcceptBirthdayGift_<taste>_<context tag> (可选)当 NPC 收到具有指定礼物喜好和上下文标签的生日礼物时显示此对话。请参阅 AcceptGift_<taste> 以获取可用的礼物喜好。

    此对话键的优先级高于 AcceptBirthdayGift_<context tag>

    AcceptGift_<taste>_<context tag> (可选)当 NPC 收到具有指定礼物喜好和上下文标签的非生日礼物时显示此对话。请参阅 AcceptGift_<taste> 以获取可用的礼物喜好。

    此对话键的优先级高于 AcceptBirthdayGift_<context tag>

    AcceptGift_<taste> (可选)当 NPC 收到具有指定礼物喜好的礼物时显示此对话。<taste> 可以是特定的喜好等级(LovedLikedNeutralDislikedHated),Positive(普通/喜欢/最爱)或Negative(不喜欢/讨厌)。

    此对话键的优先级低于所有的 AcceptGift_* 键。

    AcceptGift (可选)当 NPC 收到非生日礼物时显示此对话(如果没有找到其他 AcceptGift_* 对话键)。
    RejectBouquet_AlreadyAccepted_Engaged
    RejectBouquet_AlreadyAccepted_Married
    RejectBouquet_AlreadyAccepted
    (可选)当玩家向已经接受过花束的 NPC 赠送花束时显示。
    RejectMermaidPendant_AlreadyAccepted_Engaged
    RejectMermaidPendant_AlreadyAccepted_Married
    RejectMermaidPendant_AlreadyAccepted
    (可选)当玩家向已经接受过美人鱼吊坠的 NPC 赠送美人鱼吊坠时显示。
    RejectRoommateProposal_AlreadyAccepted
    RejectRoommateProposal_NpcWithSomeoneElse
    RejectRoommateProposal_PlayerWithSomeoneElse
    RejectRoommateProposal_LowFriendship
    RejectRoommateProposal_SmallHouse
    (可选)当 NPC 拒绝室友提议时显示,因为玩家不满足特定要求:
    • AlreadyAccepted:NPC已经是该玩家的室友。
    • NpcWithSomeoneElse:NPC已经是其他玩家的室友。
    • PlayerWithSomeoneElse:提出提议的玩家已经有室友。
    • LowFriendship:玩家与NPC的好感度未达到 10+ 心。
    • SmallHouse:玩家尚未升级房屋。
    RejectRoommateProposal (可选)当 NPC 拒绝室友提议时显示(如果没有找到更具体的 RejectRoommateProposal_* 对话)。
  • 现在使用 $y 对话命令时可以转义星号。例如, A*B 将像以前一样将 AB 分成单独的对话框,但 A**B 将显示为单个星号。

游戏状态查询变化

完整文档见模组:游戏状态查询。本章节仅对更新的内容作简单的介绍。
  • 1.6.9 添加了一些新的游戏状态查询:
    条件 效果
    DATE_RANGE <min season> <min day> <min year> [max season] [max day] [max year] 日历日期是否在指定范围内(含端点)。如果省略最大值,则默认为冬季(季节)、28(天)和无限(年)。

    例如,判断当前事件是否为第一年的夏季 15 日到冬季 15 日:

    DATE_RANGE Summer 15 1 Winter 15 1

    或秋季 15 日及以后:

    DATE_RANGE Fall 15 1
    PLAYER_BASE_COMBAT_LEVEL
    PLAYER_BASE_FARMING_LEVEL
    PLAYER_BASE_FISHING_LEVEL
    PLAYER_BASE_FORAGING_LEVEL
    PLAYER_BASE_LUCK_LEVEL
    PLAYER_BASE_MINING_LEVEL
    与非 BASE 查询相同,但忽略改变技能等级的增益效果。
    PLAYER_HAS_TRINKET <player>+ <trinket ID>+ 目标玩家是否装备了列出的饰品之一。每个 ID 可以是限定性或非限定性的物品ID。
  • 现在更多查询支持多个值,例如PLAYER_HAS_CAUGHT_FISH Current 128 139表示“玩家是否抓到了河豚鲑鱼”。此更改涉及 PLAYER_HAS_BUFFPLAYER_HAS_CAUGHT_FISHPLAYER_HAS_CONVERSATION_TOPICPLAYER_HAS_DIALOGUE_ANSWERPLAYER_HAS_HEARD_SONGPLAYER_HAS_RUN_TRIGGER_ACTIONPLAYER_HAS_SEEN_EVENTPLAYER_SPECIAL_ORDER_ACTIVEPLAYER_SPECIAL_ORDER_RULE_ACTIVEPLAYER_SPECIAL_ORDER_COMPLETE

调试命令更改

本章节文档需要迁移到模组:控制台命令。如果从此处复制内容,请在迁移后的文档处标注原作者。
  • 现在所有调试命令都会验证其参数。
  • 优化了很多情况下的异常处理。
  • 1.6.9 新增了一些调试命令:
    命令 描述
    listLights 显示所有当前活跃的光源的调试信息。
    logWallAndFloorWarnings 在将墙纸和地板应用到农舍或其他可装饰地点时开启调试日志,以便于排查故障。您通常应当在加载存档前使用此命令。
    netJoin <IP> 连接到指定 IP 地址。

    这取代了旧版的 netJoin 命令(旧版中只能打开联机菜单)。

    performTitleAction <button>
    pta <button>
    在标题界面时,跳转到指定的子菜单。
    toggleNetCompression 禁用(或重新启用)多人游戏压缩。
    toggleTimingOverlay
    tto
    在屏幕上显示一个基本计时信息框(例如,帧率),以便于分析性能表现。
    whereIsItem,
    whereItem
    列出当前存档中符合指定 ID 或名称的所有物品。

    示例:

    > debug whereItem "Watering Can"
    
    Found 1 item matching name 'Watering Can':
    - Farm > Shed at 50, 14 > Shed149bae63-2add-4ab6-a5aa-b3bd76372004 > Chest at 4, 4 > Watering Can ((T)CopperWateringCan)
    
    worldMapPosition [includeLog] 显示世界地图定位数据的详细信息,以便排查故障。若 [includeLog]true,则会打印一条详细的日志,以说明当前定位是如何根据 Data/WorldMap 数据确定的。
  • 移除了如下命令:
    命令 说明
    buildCoop 替换为了 debug build coop
  • 优化了如下命令:
    命令 改进
    achieve 现在在主机上运行此命令可以解锁相关的奖杯。
    build 现在建筑类型对大小写不敏感,且可以使用模糊匹配。
    event dontClearEvent 选项(默认为 false)已被 clearEventsSeen(默认为 true)替换了,且不再将所有值都认为是 true。
    furniture 现在允许非数字家具 ID。
    growCrops 现在适用于花盆作物。
    holdItem 添加了一个可选的 [showMessage] 布尔参数,用于在播放举起物品动画后显示该物品的信息。
    item 现在要求提供物品 ID 参数。
    mineLevel 添加了一个可选的 [layout] 参数,可以设为 Content/Maps/Mines 中的布局参数。例如,debug mineLevel 101 47 将玩家传送到矿井 101 层,并使用布局 47。
    setUpFarm clearMore 参数不再将非空值都认为是 true。
    spreadSeeds 现在适用于花盆作物。
    warpCharacterTo 添加了一个 NPC 面部朝向的独立参数,而非使用 Y 参数。
    water 现在适用于花盆作物。

翻译变化

  • 1.6 中的许多翻译从 Strings/1_6_Strings 移到了Strings/BigCraftablesStrings/ObjectsStrings/Tools
  • 工具名称/描述从 Strings/StringsFromCSFiles 移到了一个新的 Strings/Tools 素材中。动态工具名称(如“Gold {0}”)也被替换为专门名称(如“Gold Axe”),以修复翻译中的不自然之处。

建筑数据更改

本章节文档需要迁移到模组:建筑。如果从此处复制内容,请在迁移后的文档处标注原作者。

1.6.9 在 Data/Buildings 中新增了如下字段:

字段 效果
NameForGeneralType
(星露谷 1.6.15)
(可选)一个模板字符串,用于显示建筑大概类型的名称,例如“豪华鸡舍”的大概类型为“鸡舍”

。举例而言,此字段可能出现在罗宾的“开始建造”对话中。若忽略,则默认为 Name 字段。

IndoorItems 此字段在 1.6.9 之前就存在,但现在新增了一些子字段:
字段 效果
ClearTile (可选)是否移除目标地块上的所有物品,除非其符合此条目的 ItemId。若可用,则地块上之前存在的物品会被放到失物招领处。默认为 true。

动物数据更改

本章节文档需要迁移到模组:动物数据。如果从此处复制内容,请在迁移后的文档处标注原作者。
  • 1.6.9 在 Data/FarmAnimals 中新增了如下字段:
    字段 效果
    Shadow (可选)在农场动物下方绘制的阴影,如果更具体的字段(例如 ShadowWhenAdult)为空。默认为空。
  • 先前硬编码的统计数据(cowMilkProducedgoatMilkProducedsheepWoolProduced)现在可以通过 StatToIncrementOnproduce 数据字段调整。

鱼塘数据更改

完整文档见模组:鱼塘数据。本章节仅对更新的内容作简单的介绍。

添加了新字段:

字段 效果
MaxPopulation (可选)可以生活在该鱼塘中的最大鱼的数量,无论是手动添加还是自然繁殖。这不能超过硬编码的最大值 10。如果省略,则默认为 PopulationGates 的最大值。
WaterColor (可选)当游戏应用此列表项时,鱼塘水体的色调。如果指定了多个条目,则应用第一个匹配的条目。如果没有匹配项,则使用默认颜色。

此字段为包含如下字段的数据模型所组成的列表:

字段 效果
Id 此条目的唯一字符串ID
Color (可选)水体颜色。这可以是标准颜色值,或CopyFromInput(与鱼的颜色相同)。默认为空。
MinPopulation (可选)解锁此颜色所需的最小鱼数。默认为 1。
MinUnlockedPopulationGate (可选)解锁此颜色所需的最低关卡数,若设为 0 则表示不限。默认为 0。
Condition (可选)一个游戏状态查询,指示此列表项是否可用。默认为总是可用。
ProducedItems 旧版中已有此字段,但现在此字段的数据模型新增了 物品生成字段条件Id
字段 效果
Id 此列表项的唯一字符串ID
通用字段 请参阅物品生成字段以了解鱼塘奖励支持的通用物品字段。

注意:

  • 如果 ItemIdRandomItemId 是返回多个物品的物品查询,则会从中随机选择一个物品。
  • 如果 ItemIdRandomItemId 设置为字符串 (O)812鱼籽),则会生成当前鱼对应的鱼籽。
  • Condition 用于判断鱼塘中的鱼是否符合条件。

旧版的 MinQuantity/MaxQuantity 字段现已过时,并被标准的 MinStack/MaxStack 物品生成字段取代。如果内容包设置了旧字段,其值将自动应用于新字段。

物品数据更改

Data/Object

本章节文档需要迁移到模组:物体。如果从此处复制内容,请在迁移后的文档处标注原作者。
  • 新增了一个字段:
    字段 效果
    ColorOverlayFromNextIndex (可选)在将此物体作为颜色物体绘制时,是否将颜色应用于贴图集中的下一张贴图,并将后者绘制在主贴图上。若为 false,则颜色会被应用于主贴图。默认为 false。
  • 现在物体增益效果可以设置如下属性:CombatLevelAttackMultiplierCriticalChanceMultiplierCriticalPowerMultiplierImmunityKnockbackMultiplierWeaponPrecisionMultiplierWeaponSpeedMultiplier
  • 风味名称翻译类似于 Wine_Flavored_Name 可以使用新增的 {1} 标识以代表小写名称。
  • 您现在可以自定义特定风味物品的显示名称。例如,Wine_Flavored_(O)282_Name 翻译("Cranberry Wine")覆盖了 Wine_Flavored_Name ("{0} Wine").

物品生成字段

本章节文档需要迁移到模组:物品查询#物品生成字段。如果从此处复制内容,请在迁移后的文档处标注原作者。

1.6.9 为所有物品生成字段新增了一个字段:

字段 效果
Color (可选)应用于产出物品的颜色。默认为空。


其他

  • 对于 C# 模组,Object.displayNameFormat 字段现在可以使用两个新标记:%DISPLAY_NAME_LOWERCASE%PRESERVED_DISPLAY_NAME_LOWERCASE

机器数据更改

本章节文档需要迁移到模组:机器。如果从此处复制内容,请在迁移后的文档处标注原作者。

1.6.9 修复了 Data/Machines 的一些问题:

  • 现在 PreserveId 字段支持 DROP_IN_PRESERVE 标识。
  • 现在 CopyColor 字段适用于任何输入物品,即使其并非 ColoredObject(这种情况下,会使用上下文标签的颜色)。
  • 现在 CopyQuality 字段不再禁用 QualityModifiers;后者会应用于复制的结果。

地图属性变化

本章节文档需要迁移到模组:地图。如果从此处复制内容,请在迁移后的文档处标注原作者。

1.6.9添加了新的地图属性:

地图属性更改

本章节文档需要迁移到模组:地图。如果从此处复制内容,请在迁移后的文档处标注原作者。

1.6.9 新增了一些地图属性:

属性 解释
AllowBeds <allowed>
AllowMiniFridges <allowed>
迷你冰箱可否放在此地点。可以为 truefalse。若指定此参数,则会绕过通常的特殊要求(例如农舍等级),但是通用家具限制仍会生效(例如 Data/Furniture 中的“放置限制”字段)。

地图地块索引逻辑现在更安全

现在游戏能够更准确地处理地块表 ID(不区分大小写),这消除了地块索引冲突引发的错误。(但不适用于 Paths 层,以免破坏模组。您不应自定义 Paths 层地块表。)

如下代码片段反映了 1.6.8 中的海滩逻辑:

switch (getTileIndexAt(tileLocation, "Buildings"))
{
    case 284:
        if (who.Items.ContainsId("(O)388", 300))
            createQuestionDialogue(Game1.content.LoadString("Strings\\Locations:Beach_FixBridge_Question"), createYesNoResponses(), "BeachBridge");
        else
            Game1.drawObjectDialogue(Game1.content.LoadString("Strings\\Locations:Beach_FixBridge_Hint"));
        break;

这会导致任何索引为 284 的地块显示该消息,即使它属于自定义地块表。

在 1.6.9 中不再发生这种情况,因为游戏可以指定地块表 ID:

switch (getTileIndexAt(tileLocation, "Buildings", "untitled tile sheet")) // 地块表 ID 必须为 "untitled tile sheet"

宠物数据更改

本章节文档需要迁移到模组:宠物。如果从此处复制内容,请在迁移后的文档处标注原作者。

Data/Pets 中,Gifts 字段现在使用物品生成字段(包括条件和物品品质/颜色/名称/其他)。旧版的 QualifiedItemIDStack 字段已被淘汰,但设置它们的内容包应当仍能正常工作。


模板字符串更改

本章节文档需要迁移到模组:模板字符串。如果从此处复制内容,请在迁移后的文档处标注原作者。
  • 添加了新标记:
    标记格式 输出
    [CapitalizeFirstLetter <text>] 输入文本,首字母大写。
    [ItemNameWithFlavor <flavor type> <flavor ID>] 风味物品名称的译名,其中...
    • <flavor type>AgedRoeBaitDriedFruitDriedMushroomHoneyJellyJuicePickleRoeSmokedFishWine 之一;
    • <flavor ID> 是原材料的限定性或非限定性物品 ID(例如蓝莓果酒的原料是蓝莓)。
  • 对于具有自定义标记的 C# 模组,解析器(parser)将去除参数的 [EscapedText] 中的任何转义字符。

工具数据更改

Data/Tools中, ApplyUpgradeLevelToDisplayName 字段不再存在。每个工具现在都有自己的名称(请参阅翻译更改)。

触发动作更改

本章节文档需要迁移到模组:触发动作。如果从此处复制内容,请在迁移后的文档处标注原作者。

1.6.9 在 Data/TriggerActions 中添加了一个新字段:

字段 效果
SkipPermanentlyCondition (可选)此字段为一个游戏状态查询,满足此条件时,游戏会将此触发动作标记为已触发。此字段优先级高于 ConditionActionActions

此字段主要用于跳过那些不会再次触发的动作,以免每次都需要解析 Condition

其他变化

在 Stardew Valley 1.6.9 中:
  • 游戏现在始终通过 ID 查找地图地块表,从而消除了模组重排地块表导致的错误。然而,在某些情况下,游戏仍优先尝试通过索引获取地块表(因为这样更快),因此仍应避免更改地块表顺序,以免回退到 ID 查找影响性能。
  • 《海之宝石》技能书(鱼籽书)现在只适用于那些有 fish_has_roe 上下文标签的鱼。如果需要,请考虑在 Data/Objects 中为自定义鱼添加此标签。
  • 支持从任何地方获取配方物品。
  • 新增了一些统计项,以跟踪玩家完成祝尼魔赛车(completedJunimoKart)和草原之王(completedPrairieKingcompletedPrairieKingWithoutDying)的次数。对于 1.6.9 之前的存档,如果玩家至少完成过一次,则这两个统计项将被设为 1
  • 与参数解析相关的错误消息(例如在调试命令、对话、事件命令、地图属性等中)现在会显示人类可读的参数名称。例如,"required index 0 not found" 现在会显示为 "required index 0 (string itemId) not found"。
  • 现在可以出售任何类型的物品,具体取决于其 item.canBeShipped() 方法。
  • 对于事件:
    • 修复了 move 命令在找不到 NPC 时忽略其他所有 NPC 的问题。
    • 修复了 speak 命令在找不到 NPC 时结束事件的问题。
    • 修复了 GameStateQuery/G 事件前提未正确处理带引号的参数的问题。
  • 对于物品:
    • 现在上下文标签几乎总是不区分大小写。
    • Strings/1_6_Strings + Strings/StringsFromCSFiles 中的物品译名合并到 Strings/BigCraftables、<sampStrings/Objects 和 Strings/Weapons 中。
    • 修复了古代玩偶没有 doll_item 上下文标签的问题。
    • 修复了购买/拆分灵魂火把和自定义火把物品堆叠时,贴图变成默认贴图的问题。
    • 修复了物品名称可能设置为 null 的情况。现在尝试这样做时,名称将默认为“错误物品”。
  • 对于物品生成字段
    • 添加了 Color 以设置色调。
    • 修复了生成 null 物品 ID 时的错误。
  • 对于工具:
    • Strings/StringsFromCSFiles + Strings/1_6_Strings 中的工具名称/描述统一到一个新的 Strings/Tools 素材中,其键名可读性更高,如 Axe_Description
    • 每个工具升级现在都有独立的翻译(如“金斧头”),而不是像“金{0}”这样的通用翻译(这种旧版格式难以翻译)。这移除了 Data/Tools 中的 ApplyUpgradeLevelToDisplayName 字段。
    • 修复了 tool.getOne() 未复制某些工具字段的问题。
  • 对于饰品:
    • 添加了 CustomFieldsModData 数据字段供模组使用。这些取代了以前的 TrinketMetadata 字段。
    • 添加了数据字段以配置魔法箭袋忽略的地面/怪物。
    • 添加了处理某些无效数据的机制。
  • 对于游戏状态查询:
    • 修复了 HAS_TARGET_LOCATION 始终返回 true 的问题。
    • 修复了 PLAYER_HAS_ITEM 计算房主而非目标玩家的齐币的问题。
  • 对于机器:
    • 现在晶球破开器可以正确处理神秘盒(前提是模组允许晶球破开器打开神秘盒)。
    • 修复了如下问题:某些机器效果必须等到机器启动后下一次时间变化时才能生效。
    • 修复了 Data/Machines 中的 DROP_IN_PRESERVEPreserveId 字段中不起作用的问题。
    • 修复了 Data/Machines 中的 CopyColor 字段在输入不是 ColoredObject 时不起作用的问题;现在默认为其上下文标签中的颜色。
    • 修复了 Data/Machines 中的数量修饰器在具有 CopyQuality 的条目中被忽略的问题。
    • 修复了 Object.OutputAnvil 忽略其 probe 参数的问题。
    • 修复了野蜂蜜在使用 DROP_IN_PRESERVE%PRESERVED_DISPLAY_NAME 标记时生成无效物品名称的问题。
  • 对于地图:
    • 地形声音(如脚步声)现在可用于具有 TreatAsOutdoors 地图属性的地点。
    • 壁纸和地板现在可以应用于自定义地图地块(需要其地块表 ID 包含walls_and_floors)。
    • TouchAction ConditionalDoor 地块属性现在能够正确地从 Back 层获取其 LockedDoorMessage(而不是旧版中的 Buildings 层)。
    • 修复了与模组更改地块表顺序相关的错误。
    • 修复了地块索引冲突。现在游戏检查地块表 ID(不区分大小写),从而消除了与地块索引冲突相关的错误(例如自定义地块被意外地视为光照)。
    • 修复了不同平台地块表排序不一致的问题。
  • 对于 NPC 和对话:
    • 加载存档时,如果 NPC 不再位于存档前的所在地,则会被传送到 Data/Characters 中的家。(这也适用于使用 FormerCharacterNames 字段中列出的 NPC 曾用名。)
    • 使用 $y 对话命令时,可以转义星号(* 仍然是对话分隔符,但 ** 为单个星号文本)。
    • 现在可以根据与 NPC 的关系重写日程/度假对话。例如,如果您与该NPC结婚,则 rain.000_Married 会重写 rain.000。可用的关系是 FriendlyDatingEngagedMarriedDivorced
    • 改进了NPC找不到合适对话时的错误处理机制。
    • 修复了 $action 对话命令在 #$b# 分隔符后不起作用的问题。
    • 修复了命令在 #$b# 分隔符之间时显示空对话框的问题。
    • 修复了 NPC 不再应用 AcceptGift_<id> 对话键的问题。
    • 修复了 Data/Characters 外观选项默认权重不正确的问题。
    • 修复了一些友谊逻辑仍然检查 Data/NPCGiftTastes 条目而不是 Data/Characters 中的 CanSocialize 字段的问题。
  • 对于宠物:
    • Data/Pets 中的 Gifts 列表现在支持物品生成字段(包括条件、物品质量/颜色/名称等)。以前的 QualifiedItemIDStack 字段现已过时,但设置了这些字段的内容包仍应正常工作。
    • 修复了 Data/Pets 中海龟礼物 ID 与实际礼物不匹配的问题(Radish -> SeafoamPudding)。
  • 对于沙漠节变装:
    • 您现在可以为服装中指定性别变体。
    • Gender 字段现在使用 1.6 中添加的三元性别枚举。
    • 每个服装现在都有一个描述性的 Id
  • 对于烹饪/打造配方:
    • 技能等级条件的格式为 s <skill> <level><skill> <level>。由于实现方式的问题,在旧版中任何包含技能名称和等级的字符串都有效(如10boopFarming);新版会强制验证格式。
    • 修复了 Data/CraftingRecipes 输出字段中限定性物品 ID 的处理。
    • 修复了技能等级 10 的配方在等级 1 时解锁的问题。
  • 移除了未使用的素材和翻译。
  • 现在野生种子被种下时就会确定其产出,因此模组可以预测其收获。
  • 修复了对晕倒邮件文本中性别文本的支持。
  • 修复了当玩家的每日运气远超出正常范围时的崩溃问题。每日运气现在被限制在合理范围内。
  • 修复了鱼塘忽略 Data/Buildings 中的 DrawShadow 字段的问题。
  • 修复了机器和农场动物数据中的 StatIncrement 字段未使用指定 ID 的问题。
  • 修复了 AllowWakeUpWithoutBed 地图属性不协调的问题。
在 Stardew Valley 1.6.15 中:
  • 改进了建筑数据
    • 添加了一个新的 NameForGeneralType 字段。这取代了以前尝试从 Name 中解析它的硬编码逻辑。
  • 改进了鱼塘数据
    • 您现在可以通过 BaseMinProduceChanceBaseMaxProduceChance 覆盖鱼塘的基础产出几率。
    • 您现在可以通过 Precedence 字段设置产出物品的优先级。
    • 游戏不再尝试自动平衡鱼塘中的自定义传说鱼类。如果模组希望覆盖静态默认值,则可以添加自己的输出规则。
  • 改进了假人模特数据
    • 移除了 ID 字段(与键名重复)。
    • CustomFields 字段现在默认为 null(与其他素材相同)。
  • 改进了饰品数据
    • 移除了 Id 字段(与键名重复)。
  • 针对 C# 模组的更改:
    • 将更多代码标记为 public 或 virtual 以供模组使用。
    • 冰箱的 chest.sourceItem 字段不再为 null。
    • 添加了 Game1.ResetGameStateOnTitleScreen() 方法,该方法分割自 Game1.CleanupReturningToTitle()。这些方法太过专门化,大多数模组不应调用它们。
    • 修复了 NPC.CanSocializePerData 不使用给定地点的问题。
    • 修复了 farmhand.hasOrWillReceiveMail 在某些情况下检查房主玩家(而非目标玩家)邮箱的问题。
    • 修复了物品的上下文标签不随其状态更改更新的问题(例如,避免出现带 quality_none 标签的金星品质物品)。
  • 罗宾的施工开始对话中新增了一个标记,用于支持非小写建筑名称。
  • 添加了 [GenderedText][SpouseGenderedText] 标记 的可选参数,用于非二元性别文本。
  • 添加了锁门消息地块属性的两个变体:DoorUnlock_NotFriend_{npcName}(用于指定 NPC)和DoorUnlock_NotFriend_Undefined(用于非二元性别 NPC)。
  • 游戏的动态贴图现在设置了 Name 字段以简化故障排除。这些名称会显示于错误消息(如对象丢失错误)。
  • itemAboveHead 事件命令现在有一个可选参数,以设置是否显示“你收到了”消息。默认为 true(旧版中,自定义物品无法使用此参数)。
  • 移除了某些冗余的、针对游戏平台的翻译。
  • 您现在可以自定义收集品选项卡中的任何物品名称/描述(通过 Strings/Objects:<item id>_CollectionsTabName<item id>_CollectionsTabDescription)。

C#模组更改

玩家更改

  • Game1.getFarmerGame1.getFarmerMaybeOffline 方法现已过时,不应再使用。它们已被统一的 Game1.GetPlayer 方法取代。 旧方法可能存在不协调且反直觉的行为。例如,getFarmer(id)在目标玩家离线时返回主玩家,这通常不符预期。getFarmer 在玩家 ID 无效时也返回主玩家,而 getFarmerMaybeOffline 在这种情况下返回 null。新方法默认匹配离线玩家,如果未找到 ID 则返回 null (因此您可以自定义默认行为),并具有完整的代码文档和可空性注释。 迁移现有代码:
    旧代码 迁移方法
    Farmer player = Game1.getFarmer(id);
    
    旧版代码在逻辑上等价于如下代码:
    Farmer player = Game1.GetPlayer(id, onlyOnline: true) ?? Game1.MasterPlayer;
    

    但大多数模组可能并不希望这样做。或许您可以这样写:

    Farmer? player = Game1.GetPlayer(id);
    
    Farmer? player = Game1.getFarmerMaybeOffline(id);
    
    这直接等效于:
    Farmer? player = Game1.GetPlayer(id);
    
  • Game1.player 的 setter 现在是内部的。这是因为设置它会导致模组作者意想不到的副作用,故频繁引发错误和崩溃。这些在其新的代码文档中有说明。如果您坚持要直接设置它,可以使用反射。

聊天命令API

本章节文档需要迁移到模组:控制台命令。如果从此处复制内容,请在迁移后的文档处标注原作者。

聊天命令在 1.6.9 中是模块化和可扩展的。游戏提供了新的 ChatCommands API 来管理它们。

例如,您可以像这样添加自定义聊天命令:

string modId = this.ModManifest.UniqueId;
ChatCommands.Register($"{modId}_echo", this.Echo, name => $"{name} [message]: 在聊天框中显示给定的消息。");

...

/// <inheritdoc cref="ChatCommandHandlerDelegate" />
private void Echo(string[] command, ChatBox chat)
{
    string message = ArgUtility.GetRemainder(command, 1);

    chat.addInfoMessage(message);
}

屏幕阅读器变化

1.6.9 添加了字段以支持屏幕阅读器模组。这样一来,有自定义 UI 元素的模组就可以添加针对盲人玩家的信息,而无需再为每种读屏模组单独设置集成。

主要变化是一个新的接口:

/// <summary>为屏幕阅读器提供信息的UI元素。</summary>
/// <remarks>这些值不由游戏显示;它们提供用于实现屏幕阅读器模组。</remarks>
public interface IScreenReadable
{
    /// <summary>如果设置,表示此组件的翻译文本,供屏幕阅读器使用。这可能是显示的文本(对于文本组件),或等效表示(例如“退出”表示“X”按钮)。</summary>
    string ScreenReaderText { get; }

    /// <summary>如果设置,此组件的翻译工具提示式描述,供屏幕阅读器显示,除了<samp>ScreenReaderText</samp>。</summary>
    string ScreenReaderDescription { get; }

    /// <summary>这是否是纯视觉组件,应被屏幕阅读器忽略。</summary>
    bool ScreenReaderIgnore { get; }
}

这由 ClickableComponentOptionsElement 实现,因此您可以为大多数 UI 元素添加屏幕阅读器数据。

光源系统更新

1.6.9 版本对光源的跟踪方式进行了改进:

  • LightSource 现在需要一个字符串 ID (LightSource.Id),而不是之前可选的数字 ID (LightSource.Identifier)。
  • Game1.currentLightSources 现在是一个按 ID 索引的字典。(如果您添加了 using StardewValley.Extensions,仍然可以像以前一样使用 Game1.currentLightSources.Add(light)。)
  • 为每个原版光源添加了唯一的 ID。
  • 添加了针对某些问题的验证警告和自动恢复功能。
  • 在相关的辅助函数中添加了空值处理。例如,您可以将类似 if (light != null) Utility.repositionLightSource(light.Id, position) 的逻辑替换为 Utility.repositionLightSource(light?.Id, position)
  • 添加了可选的 LightSource.onlyLocation 字段,确保光源仅在查看该地点时显示。
  • 添加了代码文档。
  • 移除了 TemporaryAnimatedSprite.light 布尔字段;现在通过设置 lightId 字段来启用光源。

任务事件更新

旧版中,游戏会调用 Game1.player.checkForQuestComplete 并传入各种参数,如 string strint number2,这些参数的行为因任务类型而异。

这些方法已被更具体的方法取代,如 Quest.OnMonsterSlain,这些方法...

  • 更直观易用;
  • 接收更详细的信息(例如,怪物被击败时的伤害类型);
  • 允许自定义任务处理多种事件类型(例如,物品制作和物品接收)。

Farmer 方法已被替换为单一的 NotifyQuests 方法,该方法依次处理每个任务,并返回是否有任务被更新。

以下是旧的 Quest 方法与新方法的对应关系。(Farmer 方法与此相同,只需在它们周围添加 Game1.player.NotifyQuests(quest => ...)。)

旧代码 新代码
quest.checkForQuestComplete(npc, -1, -1, null, null, Quests.Quest.type_socialize)
quest.OnNpcSocialized(npc)
quest.checkForQuestComplete(null, -1, -1, null, buildingType, Quests.Quest.type_building)
quest.OnBuildingExists(buildingType)
quest.checkForQuestComplete(null, -1, numberCaught, null, itemId, Quest.type_fishing)
quest.OnFishCaught(itemId, numberCaught, size)
quest.checkForQuestComplete(null, -1, countAdded, item, null, Quest.type_harvest)  
quest.checkForQuestComplete(null, -1, countAdded, item, null, Quest.type_resource)
quest.OnItemReceived(item, countAdded)
quest.checkForQuestComplete(npc, -1, -1, item, "", Quests.Quest.type_harvest, Quests.Quest.type_itemDelivery)
quest.OnItemOfferedToNpc(npc, item)
quest.checkForQuestComplete(null, 1, 1, null, monster.Name, Quests.Quest.type_monster)
quest.OnMonsterSlain(location, monster, killedByBomb, isHutchSlime)
quest.checkForQuestComplete(null, -1, -1, crafted, null, Quests.Quest.type_crafting)
quest.OnRecipeCrafted(recipe, crafted)
quest.checkIfComplete(null, -1, -2, null, location.name)
quest.OnWarped(location)

两个相关的变化:

  • 建筑任务现在表示为 HaveBuildingQuest ,该类型使用上述事件。
  • completionString 字段现已过时且不再使用;您应该使用上述方法代替。

新的扩展方法

游戏在 StardewValley.Extensions 命名空间中添加了 扩展方法。这些方法为字符串等更通用的类型添加了工具方法。

1.6.9 添加了一些新的扩展方法:

方法 用法
Dictionary<TKey, TValue>.TryAddMany 将另一个字典中的所有键/值对添加到此字典中,除了已存在的键。

例如:

  
// 1.6.9 之前  
Dictionary<string, string> fields = new();  
if (obj.customFields != null)  
{  
    foreach ((string key, string value) in obj.customFields)  
        fields.TryAdd(key, value);  
}  

// 1.6.9 之后  
Dictionary<string, string> fields = new();  
fields.TryAddMany(obj.customFields);
IList<T>.RemoveWhere 从任意列表中删除所有符合条件的元素。这与 1.6 中添加的 RemoveWhere 方法等效,但适用于任何列表类型。
Layer.HasTileAt(…)
Map.HasTileAt(…)
获取地图图层上特定位置是否有地块。这与现有的 location.GetTileIndexAt(…) != -1 等效。
Map.AddTileSheet(…)` 将任意贴图集添加为地块表。
Map.RequireTileSheet(…) 通过 ID 获取地块表,如果不存在则抛出异常。
string.ContainsIgnoreCase
string.EqualsIgnoreCase
string.IndexOfIgnoreCase
string.StartsWithIgnoreCase
string.EndsWithIgnoreCase
以不区分大小写的方式比较两个字符串。

例如:

  
// 1.6.9 之前  
if (string.Equals(left, right, StringComparison.OrdinalIgnoreCase))  
   ...  

// 1.6.9 之后  
if (left.EqualsIgnoreCase(right))  
   ...

新方法还按预期处理空值。例如,如果两者都为空,left.EqualsIgnoreCase(right) 将为 true。

SyntaxAbstractor

⚠ 这是高度专业化的。 它用于原版单元测试,因此可能无法正确处理非原版文本,并且可能随时更改。

新的 SyntaxAbstractor 类将内容素材中的任意文本转换为与语言无关的句法表示。可以比较不同语言中的同一表示,以确保各翻译文本具有相同的命令序列、肖像、未本地化的元数据和分隔符等。这支持对话、事件/节日、信件和特定数据格式。

例如:

  
SyntaxAbstractor abstractor = new();  

// 对于素材
string syntax = abstractor.ExtractSyntaxFor("Characters/Dialogue/Abigail", "Sun_old", "$p 17#I guess you think nothing would happen, right?$u|Maybe a wicked ghost would appear!"); // $p 17#text$u|text  

// 对于格式  
string syntax = abstractor.ExtractMailSyntax("Hey there!^I had some extra wood lying around... I thought maybe you could use it. Take care!  ^   -Robin %item id (O)388 50 %%[#]A Gift From Robin"); // text%item id (O)388 50%%[#]text  

// 对于任意分隔数据  
string customData = "SomeKey/Example Title/An example description./Robin (O)788 Forest 110 81/-1/true/Hey, nice to see you!$h";  
int[] textFields = [1, 2];  
int[] dialogueFields = [6];  
string syntax = abstractor.ExtractDelimitedDataSyntax(customData, '/', textFields, dialogueFields); // SomeKey/text/text/Robin (O)788 Forest 110 81/-1/true/text$h

这用于单元测试,比较翻译与基础文本,以确保基本格式相同。对于单元测试,您通常通过 TranslationValidator 使用它,而不是直接使用。

TranslationValidator

新的 TranslationValidator 类将翻译与原始数据进行比较,并返回检测到的问题列表,如缺失或未知的键、语法不匹配 或语法格式错误(例如无效的性别切换块)。

例如,验证 C# 模组的翻译:

  
// 获取翻译  
var translatedData = helper.Translation.GetTranslations().ToDictionary(p => p.Key);  

// 获取基础文本  
var baseData = new Dictionary<string, Translation>();  
foreach (string key in translatedData.Keys)  
{  
    if (helper.Translation.GetInAllLocales(key).TryGetValue("default", out Translation? baseText))  
        baseData[key] = baseText;  
}  

// 断言所有测试成功  
SyntaxAbstractor abstractor = new();  
foreach (var issue in TranslationValidator.Compare(baseData, translatedData, element => element.Value, (key, value) => abstractor.ExtractDialogueSyntax(value)))  
    Assert.Fail($"验证失败:'{issue.Key}':{issue.SuggestedError}。");

工具字段和方法

  • 1.6.9 添加了许多新的工具方法和字段。例如:
    成员 用法
    对象字典 → GetValueOrDefault(…) 对象字典(如 GameLocation.objects</samp)现在实现了 .NET 的 GetValueOrDefault 方法,可以简化常见代码:
      
    // 1.6.9 之前  
    string? itemId = location.objects.TryGetValue(tile, out Object? obj)  
        ? obj.ItemId  
        : null;  
    
    // 1.6.9 之后  
    string? itemId = location.objects.GetValueOrDefault(tile)?.ItemId;
    
    Buff.customFields 用于创建增益效果的 Data/Buffs 和/或 Data/Objects 条目中的自定义字段(如果有)。
    Bush.readyForHarvest() 获取此灌木是否有果实可供收获。
    ClickableTextureComponent.drawLabel 是否应绘制标签。这允许您添加一个不会自动渲染的标签。
    ColoredObject.TrySetColor(…) 为任意物品应用色调。如果输入物品是 ColoredObject,则会直接更改该物品,否则会创建一个新的 ColoredObject 实例。

    例如:

      
    Item inputItem = ItemRegistry.Create("(O)128"); // 河豚  
    if (ColoredObject.TrySetColor(inputItem, Color.Red, out ColoredObject? coloredObj)) // coloredObj = 红色河豚  
       ...;
    
    CrabPot.NeedsBait(player) 根据玩家职业,判断蟹笼是否需要鱼饵才能捕获东西。
    CraftingRecipe.TryParseLevelRequirement(…) 尝试从烹饪/打造配方原始数据中解析技能等级要求(如果适用)。
    Crop.replaceWithObjectOnFullGrown (可选)作物完全成熟时在作物地块上的生成物体的限定性 ID。生成物体时,作物将被移除。
    Dialogue.GetFallbackForError(npc)
    Dialogue.GetFallbackTextForError()
    获取翻译后的默认“...”对话,在无法加载有效对话时显示。
    Event.TryResolveCommandName(…) 获取输入命令对应的实际命令名称。这可以用于解析别名(如 mailReceivedAddMailReceived)或规范化大小写(如 itemnamed →`ItemNamed)。

    例如:

      
    if (Event.TryResolveCommandName("mailRECEIVED", out string commandName))  
        ...; // commandName = AddMailReceived
    
    FarmAnimal.homeInterior 动物建筑的内部地点。
    FarmHouse.GetFridgePositionFromMap() 通过扫描地块获取冰箱的位置。(大多数代码应使用缓存的 fridgePosition 字段代替。)
    FruitTree.GetCosmeticSeason()` 获取当前果树贴图对应的实际季节(不一定是其产果的季节。一般情况下返回所在地点的季节,若所在地点忽略季节则返回夏季)。这主要用于让模组重写逻辑。
    Game1.IsHudDrawn 用户界面元素(如工具栏)当前是否可见。
    Game1.locationData Data/Locations 素材的缓存视图。
    GameLocation.CanWakeUpHere() 判断玩家是否可以在此地点醒来,而不是被传送回家。
    GameLocation.ForEachDirt(…) 对地点中的每个耕地执行操作。您可以选择排除花盆中的耕地。

    例如:

      
    Game1.currentLocation.ForEachDirt(dirt =>  
    {  
        dirt.Pot?.Water();  
        dirt.state.Value = HoeDirt.watered;  
        return true;  
    });
    
    GameLocation.GetHarvestSpawnedObjectQuality(…) 获取收获生成物品(如采集品)时的质量。
    GameLocation.GetAddedMapOverrideTilesheetId(…)` 获取通过 location.ApplyMapOverride(…) 添加的地块表的动态 ID。
    `GameLocation.removeMapTile(…)` 移除给定图层和位置上的地块。
    GameLocation.setMapTile(…) 添加或覆盖给定图层和位置上的地块。可以同时设置 Action 地块属性。除非您指定了 copyProperties: false,否则游戏会自动复制任何先前的地块属性。

    这统一了以前的 setMapTilesetMapTileIndex 方法。请注意,将索引设置为 -1 并不会删除地块;如需删除地块,请使用 removeMapTile

    GameLocation.hasTileAt(…) 获取地图图层上特定位置是否有地块。这与现有的 GetTileIndexAt(…) != -1 等效。
    GameLocation.OnHarvestedForage(…) 当玩家收获采集品时,授予采集或耕种经验值,以及执行模组定义的其他行为。
    GameLocation.ParentBuilding 包含此地点的建筑(如果适用)。这取代了以前的 GetContainingBuilding() 方法,以避免每次调用时遍历父地点的建筑列表。
    HoeDirt.Pot 有耕地的花盆(如果适用)。这由游戏自动设置。
    Inventory.IsLocalPlayerInventory 这是否为 Game1.player 的主背包。
    Inventory.Reduce(…) 从背包的指定物品堆叠扣除指定数量的物品。如果该物品堆叠被清空,您可以指定是否继续扣除背包中具有相同 ID 的其他物品,直到扣除数量达到指定数量,或无法继续扣除。如果某一堆叠的堆叠数被扣除至零,则会清空相应槽位。

    这与 player.reduceActiveItemByOne() 类似,但它并不要求玩家选中物品堆叠,并且允许减少任意数量。例如:

      
    Item item = ...;  
    int countRemoved = Game1.player.Reduce(item, 5, reduceRemainderFromInventory: false);
    
    Item.BaseName 如果物品的 Name 包含临时动态更改(如配方后缀),则返回未经更改的物品名称。
    Item.canBeShipped() 判断此物品是否可以放入出货箱。这取代了以前的 Object.canBeShipped(),现在返回 true 适用于任何物品类型。
    Item.CopyFieldsFrom(otherItem) 将另一个物品的所有字段复制到当前物品中。这与 item.getOne() 等效,只不过更新的是现有物品。
    LocalizedContentManager.LoadBaseStringOrNull(…) 获取翻译路径的默认英文文本,如果未找到则返回 null
    Item.LearnRecipe() 学习此物品的配方(无论配方是在 Data/CookingRecipes 还是 Data/CraftingRecipes 中)。
    NPC.CanSocializePerData(…) 根据 NPC 在 Data/Characters 中的条目,获取是否应启用社交功能(如生日、送礼、友谊和社交标签中的条目)。这与 npc.CanSocialize 等效,但不需要 NPC 的实例。
    Object.GetPreservedItemId() 获取此风味物品的原料 ID(例如,郁金香蜂蜜的原料为郁金香),如果适用。这与 item.preservedParentSheetIndex 等效,但在特殊情况下(如野蜂蜜,其中 preservedParentSheetIndex 设置为非物品值,如 -1)除外。
    Object.IsTextSign() 获取物品是否可以具有可编辑的悬停文本,如文字标牌
    Object.GetObjectDisplayName(…) 获取物品的显示名称,而无需创建物品实例。
    Raccoon.GetBundle()
    Raccoon.GetBundle(timesFed)
    获取当前或将完成给定数量的收集包后显示的 浣熊收集包
    Utility.fuzzySearchAll(…) 根据模糊比较规则查找搜索词的所有匹配项。

    例如:

      
    IEnumerable<string> coopNames = Utility.FuzzySearchAll("coop", Game1.buildingData.Keys); // [ "Coop", "Big Coop", "Deluxe Coop" ]
    
    WorldDate.GetDaysPlayed(…) 获取从游戏开始到给定日期的总天数,以便进行高效的日期比较。

    例如:

      
    int minDaysPlayed = WorldDate.GetDaysPlayed(year, season, dayOfMonth);  
    int actualDaysPlayed = Game1.Date.TotalDays;  
    if (actualDaysPlayed >= minDaysPlayed)  
       ...;
    
  • 改进了许多现有字段和方法。例如:
    成员 更改
    ArgUtility.UnsplitQuoteAware
    • 您现在可以设置可选的起始索引和最大数量,故无需在合并所需参数前复制数组。
    • 当给定空数组时,它现在返回空字符串而不是 null,以匹配其他 ArgUtility 方法。
    GameLocation.getTileIndexAt(…)
    Layer.GetTileIndexAt(…)
    Map.GetTileIndexAt(…)
    添加了 string tilesheetId = null 参数,如果设置,则检查指定地块表中的地块索引。
    LocalizedContentManager.LoadStringReturnNullIfNotFound(…) 添加了可选的替换参数和可选的 localeFallback 参数。
    MineShaft.IsGeneratedLevel(…)
    VolcanoDungeon.IsGeneratedLevel(…)
    添加了不带 out 参数的重载,以简化常见逻辑。例如:
      
    if (MineShaft.IsGeneratedLevel(location))  
       ...;
    
    ResourceClump.IsGreenRainBush() 判断此资源团块否为特殊的绿雨灌木(看起来像巨型杂草)。
    Utility.consolidateStacks(…) 当物品堆叠被移除时,它会将该索引设置为 null 而不是删除索引,因此可以安全地用于玩家背包。

    如果您的代码不期望列表中有空条目,则可以在合并后移除它们:

      
    Utility.consolidateStacks(itemList);  
    itemList.RemoveWhere(slot => slot is null);
    
  • 并移除了各种方法,包括...
    成员 替代方案
    GameLocation.refurbishMapPortion(…) 使用 location.ApplyMapOverride 代替。
    GameLocation.setMapTileIndex(…) 使用 location.setMapTile 代替。

新常量

1.6.9 添加了新的常量:

常量 用法
AchievementIds.* Data/Achievements 中成就的 ID。例如:
  
// 1.6.9 之前  
if (player.achievements.Contains(34))  
   ...;  

// 1.6.9 之后  
if (player.achievements.Contains(AchievementIds.FullShipment))  
   ...;
GameLocation.DefaultTileSheetId
MineShaft.MainTileSheetId
MovieTheater.MainTileSheetId
Submarine.MainTileSheetId
VolcanoDungeon.MainTileSheetId
每个位置的主地块表 ID:默认(untitled tile sheet)、矿井(mine)、电影院(movieTheater_tileSheet)、潜艇(submarine tiles)和火山地牢(dungeon)。
Item.ErrorItemName 无效物品显示的“错误物品”名称。
SpecialCurrencyDisplay.currency_qiGems
SpecialCurrencyDisplay.currency_walnuts
该货币界面支持的货币类型(例如获得齐钻金色核桃在左上角显示的界面)。

ForEachItem更改

1.6.9 中对 ForEachItem 方法进行了一些更改。(这些方法遍历世界中的每个物品,并选择移除/替换实例。)

大多数模组不受影响。这影响使用 ForEachItem 的高级形式(如 Utility.ForEachItem((item, remove, replaceWith) => ...))的模组,或实现自定义物品类型的模组。使用简单形式(如 Utility.ForEachItem(item => ...))的模组不需要任何更改。

主要更改包括:

  • 高级形式现在使用上下文对象,该对象还提供物品的“路径”。例如,箱子内的物品将具有由地点和箱子组成的路径:
      
    Utility.ForEachItemContext(delegate(in ForEachItemContext context)  
    {  
        // 移除箱子内的河豚  
         if (context.Item.QualifiedItemId == "(O)128" && context.GetPath().Last() is Chest)  
            context.RemoveItem();  
        return true;  
    });
    

    必须使用 in 关键字通过引用传递上下文。这不适用于 lambda 表达式,因此您需要调整格式:

      
    // ✘ lambda 不能使用 'in'  
    Utility.ForEachItemContext(in context =>  
    {  
        context.RemoveItem();  
        return true;  
    });  
    
    // ✓ 使用方法或局部函数  
    bool HandleItem(in ForEachItemContext context)  
    {  
        context.RemoveItem();  
        return true;  
    }  
    Utility.ForEachItemContext(HandleItem);  
    
    // ✓ 使用委托  
    Utility.ForEachItemContext(delegate(in ForEachItemContext context)  
    {  
        context.RemoveItem();  
        return true;  
    });
    
  • 对于重写 Item.ForEachItem 的自定义物品,旧版方法签名为
      
    /// <summary>对此物品中包含的每个物品执行操作(例如,存储在箱子中的物品、放在桌子上的物品等)。这不包括物品本身。</summary>  
    /// <param name="handler">对每个物品执行的操作。</param>  
    /// <returns>返回是否继续迭代。</returns>  
    bool ForEachItem(ForEachItemDelegate handler);
    

    新版方法签名为:

      
    /// <summary>对此物品中包含的每个物品执行操作(例如,存储在箱子中的物品、放在桌子上的物品等)。这不包括物品本身。</summary>  
    /// <param name="handler">对每个物品执行的操作。</param>  
    /// <param name="getPath">导致此物品的上下文路径(包括物品),或 <c>null</c> 以将此视为根。</param>  
    /// <returns>返回是否继续迭代。</returns>  
    bool ForEachItem(ForEachItemDelegate handler, GetForEachItemPathDelegate getPath);
    
    您应当将 getPath 值传递给 ForEachItemHelper 方法。

OutputMethodData/Machines中的更改

本章节文档需要迁移到模组:机器。如果从此处复制内容,请在迁移后的文档处标注原作者。

如果您为 Data/Machines 中的 OutputMethod 字段指定了自定义方法,则在 1.6.9 中须更改其方法签名。您需要将新的 Farmer player 参数添加到方法中:

/// <summary>The method signature for a custom <see cref="MachineItemOutput.OutputMethod"/> method.</summary>
/// <param name="machine">The machine instance for which to produce output.</param>
/// <param name="inputItem">The item being dropped into the machine, if applicable.</param>
/// <param name="probe">Whether the machine is only checking the output that would be produced. If so, the input/machine shouldn't be changed and no animations/sounds should play.</param>
/// <param name="outputData">The item output data from <c>Data/Machines</c> for which output is being created, if applicable.</param>
/// <param name="player">The player interacting with the machine, if any.</param>
/// <param name="overrideMinutesUntilReady">The in-game minutes until the item will be ready to collect, if set. This overrides the equivalent fields in the machine data if set.</param>
/// <returns>Returns the item to produce, or <c>null</c> if none should be produced.</returns>
public delegate Item MachineOutputDelegate(Object machine, Item inputItem, bool probe, MachineItemOutput outputData, Farmer player, out int? overrideMinutesUntilReady);

其他更改

  • 对于物品:
    • Object.signText 现在可以使用 模板字符串。新的 SignText 属性用于存储解析后的显示文本。
  • 对于饰品:
    • trinket.OnDamageMonster 方法现在接收 isBombisCriticalHit 参数。
    • 对于 C# 模组,添加了新的命名空间和代码文档,使更多代码公开,重命名字段以提高清晰度等。
    • 修复了 Trinket.getOne() 未复制饰品字段的问题。
    • 修复了 TrinketEffect.GenerateRandomStats() 调用构造函数后再次调用就不能正确更新描述的问题。
  • UI 更改:
    • 添加了 [屏幕阅读器字段](https://stardewvalleywiki.com/Modding:Migrate_to_Stardew_Valley_1.6.9#Screen_reader_changes)。
    • 添加了 ItemGrabMenu 构造函数以复制现有菜单(例如,需要重新打开菜单)。
    • 重写了 Game1.specialCurrencyDisplay。它现在可以同时处理和显示多种货币,具有常量和完整的代码文档,并且无需手动管理持久显示(例如在菜单打开时)。
    • 菜单中的默认手柄导航已经自动检测到公共 List<T> 和一些 Dictionary<TKey, TValue> 字段中的 ClickableComponent 值。现在它适用于任何 ClickableComponent 子类和任何字典键/值类型的组合。
    • 修复了库存 UI 中的整理按钮重置各种菜单选项的问题。
  • 添加了 新的 Game1.GetPlayer 方法,弃用了旧的 getFarmergetFarmerMaybeOffline 方法。
  • 添加了对 Game1.multiplayer.broadcastGlobalMessage 参数中模板字符串的支持。
  • Data/Machines 中,OutputMethod C# 方法现在也会获取与机器交互的玩家(如果有)。不幸的是,这对于具有自定义 OutputMethod 方法的 C# 模组来说是一个破坏性更改。
  • 物品数据现在加载得更早,因此模组可以在加载其他素材时使用它(例如在生成地点鱼类时检查物品上下文标签)。
  • Object.displayNameFormat 字段现在在多人游戏中同步,以允许模组创建自定义的非临时物品。
  • 更改了 IClickableMenu.draw(SpriteBatch b, int red = -1, int green = -1, int blue = -1)</cide> 的签名,使参数不再是可选的,这修复了与 draw(SpriteBatch b) 的冲突。
  • 现在可以使用 Game1.enterMineMineShaft.GetLevelNameforceLayout 参数强制传送到特定的矿井布局。
  • ItemStockInformation 现在是一个类而不是结构体,这避免了在编辑商店库存时出现反直觉的行为。
  • LanguageSelectionMenu 被重写以稍微去硬编码语言支持。
  • ShopMenuonPurchase 回调现在接收库存信息,并使用文档化的委托。
  • 任务和特殊订单现在可以选择计算在农场杀死的野生怪物(默认 false)。您可以配置 Data/Quests 中的击杀任务目标字段的第四个参数,以及在 Data/SpecialOrders 中的击杀目标的 Data 字段中的 IgnoreFarmMonsters
  • 修复了沙漠节换装无法调用帽子/服装的 onEquip/onUnEquip 方法的问题。
  • 修复了 location.playTerrainSound 根据玩家当前地点而不是调用它的地点改变声音的问题。
  • 修复了 Utility.tryToPlaceItem 接受 Item 参数而不是 Object 的问题,尽管它在接受非 Object 值时会抛出异常。
  • 修复了以非默认比例绘制农民时渲染错误的问题。
  • 修复了在某些情况下可以在 TriggerActionManager 完全初始化之前调用它的问题。
  • 修复了在销毁或未放置的灌木上调用某些 Bush 方法时的错误。
  • 修复了如下问题:调用 TriggerActionManager.RegisterAction 注册两个名称相同的触发动作时,出现一则警告文本,该文本错误地声称游戏将使用较新值。
  • 添加了更多代码文档。
  • 为模组公开了更多代码。
  • 移除了最后的 Net 字段隐式转换运算符(用于 NetBoolNetIntNetString)。
  • 移除了未使用的类型、字段/属性和方法。
  • 调整了能力选项卡的代码,以便模组可以获取某一槽位的对应的能力 ID。

SMAPI和外部工具的更改

内容哈希

游戏现在有一个 Content/ContentHashes.json 文件,其中包含每个原版内容素材的 MD5 哈希值。这使得 SMAPI、模组管理器和其他工具可以自动检测过时、损坏、丢失或被XNB 模组 替换的内容文件。

译名更改

此节主要介绍各语言的译名更改,用于辅助维基编辑者更新相应页面。详见英语页面

对XNB的影响

概览

本节提供了《星露谷物语 1.6》中 XNB 文件更改的摘要。这不包括新文件(因为它们不会影响旧版模组),也不包括非英文文件中的文本更改。

XNB 模组会受到不成比例的影响,因为...

  1. 它们会替换整个文件;
  2. 它们通过 MonoGame 内容管道加载,该管道对格式变化的容忍度较低;
  3. 它们无法受益于Content Patcher为其内容包提供的兼容性重写。

Content Patcher 包通常不受影响(Content Patcher 会尝试自动重写内容包)。不过,如果内容包直接替换素材而非编辑素材,则更有可能像 XNB 模组一样受到影响。

素材更改

TODO

移除无用素材

Stardew Valley 1.6.9 删除了游戏未使用的素材。模组通常不受此影响。

移除的素材:

  • LooseSprites/buildingPlacementTiles
  • LooseSprites/DialogBoxGreen
  • LooseSprites/hoverBox
  • LooseSprites/robinAtWork
  • LooseSprites/skillTitles
  • Maps/cavedarker
  • Maps/FarmhouseTiles
  • Maps/GreenhouseInterior
  • Maps/spring_BusStop
  • Maps/TownIndoors
  • Maps/WizardHouseTiles
  • Maps/WoodBuildings
  • TerrainFeatures/BuffsIcons

另请参阅