第1行: |
第1行: |
− | ← [[模组:目录]] | + | ←[[模组: 目录| 目录]] |
| + | {{翻译}} |
| + | This page explains how the game stores and parses fruit tree data. This is an advanced guide for mod developers. |
| | | |
− | 此页面解释游戏是如何存储和解析果树数据
| + | ==Raw data== |
| + | Fruit tree data is stored in <samp>Content\Data\FruitTrees.xnb</samp>, which can be [[Modding:Editing XNB files#unpacking|unpacked for editing]]. Here's the raw data as of {{version|1.6.8}} for reference: |
| | | |
− | == 原始数据== | + | {{collapse|Data|content=<syntaxhighlight lang="json"> |
− | 果树数据存储在<samp>Content\Data\FruitTrees.xnb</samp> 中
| + | { |
| + | "628": { |
| + | "PlantableLocationRules": null, |
| + | "DisplayName": "[LocalizedText Strings\\Objects:Cherry_Name]", |
| + | "Seasons": [ |
| + | "Spring" |
| + | ], |
| + | "Fruit": [ |
| + | { |
| + | "Season": null, |
| + | "Chance": 1.0, |
| + | "Condition": null, |
| + | "Id": "Default", |
| + | "ItemId": "(O)638", |
| + | "RandomItemId": null, |
| + | "MaxItems": null, |
| + | "MinStack": -1, |
| + | "MaxStack": -1, |
| + | "Quality": -1, |
| + | "ObjectInternalName": null, |
| + | "ObjectDisplayName": null, |
| + | "ToolUpgradeLevel": -1, |
| + | "IsRecipe": false, |
| + | "StackModifiers": null, |
| + | "StackModifierMode": "Stack", |
| + | "QualityModifiers": null, |
| + | "QualityModifierMode": "Stack", |
| + | "ModData": null, |
| + | "PerItemCondition": null |
| + | } |
| + | ], |
| + | "Texture": "TileSheets\\fruitTrees", |
| + | "TextureSpriteRow": 0, |
| + | "CustomFields": null |
| + | }, |
| + | "629": { |
| + | "PlantableLocationRules": null, |
| + | "DisplayName": "[LocalizedText Strings\\Objects:Apricot_Name]", |
| + | "Seasons": [ |
| + | "Spring" |
| + | ], |
| + | "Fruit": [ |
| + | { |
| + | "Season": null, |
| + | "Chance": 1.0, |
| + | "Condition": null, |
| + | "Id": "Default", |
| + | "ItemId": "(O)634", |
| + | "RandomItemId": null, |
| + | "MaxItems": null, |
| + | "MinStack": -1, |
| + | "MaxStack": -1, |
| + | "Quality": -1, |
| + | "ObjectInternalName": null, |
| + | "ObjectDisplayName": null, |
| + | "ToolUpgradeLevel": -1, |
| + | "IsRecipe": false, |
| + | "StackModifiers": null, |
| + | "StackModifierMode": "Stack", |
| + | "QualityModifiers": null, |
| + | "QualityModifierMode": "Stack", |
| + | "ModData": null, |
| + | "PerItemCondition": null |
| + | } |
| + | ], |
| + | "Texture": "TileSheets\\fruitTrees", |
| + | "TextureSpriteRow": 1, |
| + | "CustomFields": null |
| + | }, |
| + | "630": { |
| + | "PlantableLocationRules": null, |
| + | "DisplayName": "[LocalizedText Strings\\Objects:Orange_Name]", |
| + | "Seasons": [ |
| + | "Summer" |
| + | ], |
| + | "Fruit": [ |
| + | { |
| + | "Season": null, |
| + | "Chance": 1.0, |
| + | "Condition": null, |
| + | "Id": "Default", |
| + | "ItemId": "(O)635", |
| + | "RandomItemId": null, |
| + | "MaxItems": null, |
| + | "MinStack": -1, |
| + | "MaxStack": -1, |
| + | "Quality": -1, |
| + | "ObjectInternalName": null, |
| + | "ObjectDisplayName": null, |
| + | "ToolUpgradeLevel": -1, |
| + | "IsRecipe": false, |
| + | "StackModifiers": null, |
| + | "StackModifierMode": "Stack", |
| + | "QualityModifiers": null, |
| + | "QualityModifierMode": "Stack", |
| + | "ModData": null, |
| + | "PerItemCondition": null |
| + | } |
| + | ], |
| + | "Texture": "TileSheets\\fruitTrees", |
| + | "TextureSpriteRow": 2, |
| + | "CustomFields": null |
| + | }, |
| + | "631": { |
| + | "PlantableLocationRules": null, |
| + | "DisplayName": "[LocalizedText Strings\\Objects:Peach_Name]", |
| + | "Seasons": [ |
| + | "Summer" |
| + | ], |
| + | "Fruit": [ |
| + | { |
| + | "Season": null, |
| + | "Chance": 1.0, |
| + | "Condition": null, |
| + | "Id": "Default", |
| + | "ItemId": "(O)636", |
| + | "RandomItemId": null, |
| + | "MaxItems": null, |
| + | "MinStack": -1, |
| + | "MaxStack": -1, |
| + | "Quality": -1, |
| + | "ObjectInternalName": null, |
| + | "ObjectDisplayName": null, |
| + | "ToolUpgradeLevel": -1, |
| + | "IsRecipe": false, |
| + | "StackModifiers": null, |
| + | "StackModifierMode": "Stack", |
| + | "QualityModifiers": null, |
| + | "QualityModifierMode": "Stack", |
| + | "ModData": null, |
| + | "PerItemCondition": null |
| + | } |
| + | ], |
| + | "Texture": "TileSheets\\fruitTrees", |
| + | "TextureSpriteRow": 3, |
| + | "CustomFields": null |
| + | }, |
| + | "632": { |
| + | "PlantableLocationRules": null, |
| + | "DisplayName": "[LocalizedText Strings\\Objects:Pomegranate_Name]", |
| + | "Seasons": [ |
| + | "Fall" |
| + | ], |
| + | "Fruit": [ |
| + | { |
| + | "Season": null, |
| + | "Chance": 1.0, |
| + | "Condition": null, |
| + | "Id": "Default", |
| + | "ItemId": "(O)637", |
| + | "RandomItemId": null, |
| + | "MaxItems": null, |
| + | "MinStack": -1, |
| + | "MaxStack": -1, |
| + | "Quality": -1, |
| + | "ObjectInternalName": null, |
| + | "ObjectDisplayName": null, |
| + | "ToolUpgradeLevel": -1, |
| + | "IsRecipe": false, |
| + | "StackModifiers": null, |
| + | "StackModifierMode": "Stack", |
| + | "QualityModifiers": null, |
| + | "QualityModifierMode": "Stack", |
| + | "ModData": null, |
| + | "PerItemCondition": null |
| + | } |
| + | ], |
| + | "Texture": "TileSheets\\fruitTrees", |
| + | "TextureSpriteRow": 4, |
| + | "CustomFields": null |
| + | }, |
| + | "633": { |
| + | "PlantableLocationRules": null, |
| + | "DisplayName": "[LocalizedText Strings\\Objects:Apple_Name]", |
| + | "Seasons": [ |
| + | "Fall" |
| + | ], |
| + | "Fruit": [ |
| + | { |
| + | "Season": null, |
| + | "Chance": 1.0, |
| + | "Condition": null, |
| + | "Id": "Default", |
| + | "ItemId": "(O)613", |
| + | "RandomItemId": null, |
| + | "MaxItems": null, |
| + | "MinStack": -1, |
| + | "MaxStack": -1, |
| + | "Quality": -1, |
| + | "ObjectInternalName": null, |
| + | "ObjectDisplayName": null, |
| + | "ToolUpgradeLevel": -1, |
| + | "IsRecipe": false, |
| + | "StackModifiers": null, |
| + | "StackModifierMode": "Stack", |
| + | "QualityModifiers": null, |
| + | "QualityModifierMode": "Stack", |
| + | "ModData": null, |
| + | "PerItemCondition": null |
| + | } |
| + | ], |
| + | "Texture": "TileSheets\\fruitTrees", |
| + | "TextureSpriteRow": 5, |
| + | "CustomFields": null |
| + | }, |
| + | "69": { |
| + | "PlantableLocationRules": null, |
| + | "DisplayName": "[LocalizedText Strings\\Objects:Banana_Name]", |
| + | "Seasons": [ |
| + | "Summer" |
| + | ], |
| + | "Fruit": [ |
| + | { |
| + | "Season": null, |
| + | "Chance": 1.0, |
| + | "Condition": null, |
| + | "Id": "Default", |
| + | "ItemId": "(O)91", |
| + | "RandomItemId": null, |
| + | "MaxItems": null, |
| + | "MinStack": -1, |
| + | "MaxStack": -1, |
| + | "Quality": -1, |
| + | "ObjectInternalName": null, |
| + | "ObjectDisplayName": null, |
| + | "ToolUpgradeLevel": -1, |
| + | "IsRecipe": false, |
| + | "StackModifiers": null, |
| + | "StackModifierMode": "Stack", |
| + | "QualityModifiers": null, |
| + | "QualityModifierMode": "Stack", |
| + | "ModData": null, |
| + | "PerItemCondition": null |
| + | } |
| + | ], |
| + | "Texture": "TileSheets\\fruitTrees", |
| + | "TextureSpriteRow": 7, |
| + | "CustomFields": null |
| + | }, |
| + | "835": { |
| + | "PlantableLocationRules": null, |
| + | "DisplayName": "[LocalizedText Strings\\Objects:Mango_Name]", |
| + | "Seasons": [ |
| + | "Summer" |
| + | ], |
| + | "Fruit": [ |
| + | { |
| + | "Season": null, |
| + | "Chance": 1.0, |
| + | "Condition": null, |
| + | "Id": "Default", |
| + | "ItemId": "(O)834", |
| + | "RandomItemId": null, |
| + | "MaxItems": null, |
| + | "MinStack": -1, |
| + | "MaxStack": -1, |
| + | "Quality": -1, |
| + | "ObjectInternalName": null, |
| + | "ObjectDisplayName": null, |
| + | "ToolUpgradeLevel": -1, |
| + | "IsRecipe": false, |
| + | "StackModifiers": null, |
| + | "StackModifierMode": "Stack", |
| + | "QualityModifiers": null, |
| + | "QualityModifierMode": "Stack", |
| + | "ModData": null, |
| + | "PerItemCondition": null |
| + | } |
| + | ], |
| + | "Texture": "TileSheets\\fruitTrees", |
| + | "TextureSpriteRow": 8, |
| + | "CustomFields": null |
| + | } |
| + | } |
| + | </syntaxhighlight>}} |
| + | |
| + | ====Data format==== |
| + | The <samp>Data/FruitTrees</samp> asset consists of a string → model lookup, where... |
| + | * The key is the unqualified item it for the sapling item in <samp>Data/Objects</samp>. |
| + | * The value is a model with the fields listed below. |
| | | |
− | ===数据格式===
| |
| {| class="wikitable" | | {| class="wikitable" |
| |- | | |- |
− | ! 字段 | + | ! field |
− | ! 说明 | + | ! effect |
| |- | | |- |
| | <samp>DisplayName</samp> | | | <samp>DisplayName</samp> |
− | | 这是个可标记字符串,用于放置树的名字。这应该返回一个不带“tree”的放置名( 例如 <samp>Cherry</samp> 表示樱桃树) 。这使用于 UI 信息中像 "''Your <display name> tree wasn't able to grow last night''". | + | | A [[Modding:Tokenizable strings|tokenizable string]] for the tree's display name. This should return a display name without 'tree' (like <samp>Cherry</samp> for a cherry tree). This is used in UI messages like "''Your <display name> tree wasn't able to grow last night''". |
| |- | | |- |
| | <samp>Seasons</samp> | | | <samp>Seasons</samp> |
− | | 果树能结出果实的季节。它是由季节组组成(<samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, <samp>winter</samp>) 。 | + | | The seasons in which the fruit tree bears fruit. This consists of an array of season names (any combination of <samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, or <samp>winter</samp>). |
| | | |
| '''Note:''' the previous '<samp>island</samp>' season value is no longer valid. Using <samp>summer</samp> is equivalent to how it worked before (since we now have [[#Custom location contexts|per-location seasons]]). | | '''Note:''' the previous '<samp>island</samp>' season value is no longer valid. Using <samp>summer</samp> is equivalent to how it worked before (since we now have [[#Custom location contexts|per-location seasons]]). |
第83行: |
第364行: |
| | The [[Modding:Common_data_field_types#Custom_fields|custom fields]] for this entry. | | | The [[Modding:Common_data_field_types#Custom_fields|custom fields]] for this entry. |
| |} | | |} |
| + | |
| + | For example, this content pack adds a custom fruit tree, including [[Modding:Items|custom items]] for the sapling and fruit: |
| + | |
| + | {{#tag:syntaxhighlight|<nowiki> |
| + | { |
| + | "Format": "</nowiki>{{Content Patcher version}}<nowiki>", |
| + | "Changes": [ |
| + | // add fruit + sapling items |
| + | // note: sapling must have an edibility under 0 (usually -300) to be plantable |
| + | { |
| + | "Action": "EditData", |
| + | "Target": "Data/Objects", |
| + | "Entries": { |
| + | "{{ModId}}_Pufferfruit": { |
| + | "Name": "{{ModId}}_Pufferfruit", // best practice to match the ID, since it's sometimes used as an alternate ID |
| + | "DisplayName": "Pufferfruit", |
| + | "Description": "An example fruit item.", |
| + | "Type": "Basic", |
| + | "Category": -6, |
| + | "Price": 1200, |
| + | |
| + | "Texture": "Mods/{{ModId}}/Objects", |
| + | "SpriteIndex": 0 |
| + | }, |
| + | "{{ModId}}_Puffersapling": { |
| + | "Name": "{{ModId}}_Puffersapling", |
| + | "DisplayName": "Puffersapling", |
| + | "Description": "An example tree sapling.", |
| + | "Type": "Basic", |
| + | "Category": -74, |
| + | "Price": 1200, |
| + | |
| + | "Texture": "Mods/{{ModId}}/Objects", |
| + | "SpriteIndex": 1 |
| + | } |
| + | } |
| + | }, |
| + | |
| + | // add fruit tree |
| + | { |
| + | "Action": "EditData", |
| + | "Target": "Data/FruitTrees", |
| + | "Entries": { |
| + | "{{ModId}}_Puffersapling": { |
| + | "DisplayName": "Pufferfruit", |
| + | "Seasons": [ "spring" ], |
| + | "Fruit": [ |
| + | { |
| + | "Id": "E{{ModId}}_Pufferfruit", |
| + | "ItemId": "{{ModId}}_Pufferfruit" |
| + | } |
| + | ], |
| + | "Texture": "Mods/{{ModId}}/FruitTrees", |
| + | "TextureSpriteRow": 0 |
| + | } |
| + | } |
| + | }, |
| + | |
| + | // add images |
| + | { |
| + | "Action": "Load", |
| + | "Target": "Mods/{{ModId}}/FruitTrees, Mods/{{ModId}}/Objects", |
| + | "FromFile": "assets/{{TargetWithoutPath}}.png" // assets/FruitTrees.png, assets/Objects.png |
| + | }, |
| + | ] |
| + | }</nowiki>|lang=javascript}} |
| + | |
| + | The fruit trees can then be added to the game by giving the player a sapling item in the usual ways (e.g. from [[#Custom shops|a shop]]). |
| + | |
| + | ====Fruit items==== |
| + | For C# mods, the <samp>fruitsOnTree</samp> field (number of fruit on the tree) has been replaced by <samp>fruit</samp> (list of fruit items). |
| + | |
| + | ====Spawning fruit trees==== |
| + | Custom trees can be added to the game in two ways: |
| + | * Spawn them on [[Modding:Maps|map tiles]] when the location is created, using the new <samp>SpawnTree: fruit {{t|tree ID}} {{o|growth stage on location created}} {{o|growth stage on day-update regrowth}}</samp> tile property. This must be added on the <samp>Paths</samp> layer, which must also have tile index 34 from the <samp>paths</samp> tilesheet. |
| + | * Or give the player a seed item in the usual ways (e.g. from [[#Custom shops|a shop]], [[Modding:Mail data|mail letter]], etc). |
| + | |
| + | [[Category:模组]] |
| + | |
| + | [[en:Modding:Fruit trees]] |