Modding:Fruit trees
← Index
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 Content\Data\FruitTrees.xnb, which can be unpacked for editing. Here's the raw data as of 1.6.8 for reference:
Data |
---|
{
"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
}
}
|
Data format
The Data/FruitTrees asset consists of a string → model lookup, where...
- The key is the unqualified item it for the sapling item in Data/Objects.
- The value is a model with the fields listed below.
field | effect | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DisplayName | A tokenizable string for the tree's display name. This should return a display name without 'tree' (like Cherry for a cherry tree). This is used in UI messages like "Your <display name> tree wasn't able to grow last night". | ||||||||||||
Seasons | The seasons in which the fruit tree bears fruit. This consists of an array of season names (any combination of spring, summer, fall, or winter).
Note: the previous 'island' season value is no longer valid. Using summer is equivalent to how it worked before (since we now have per-location seasons). | ||||||||||||
Fruit | The fruit items to add to the tree each day while the tree is in-season. The first matching fruit (if any) is selected each day.
This consists of a list of models with these fields:
| ||||||||||||
Texture | The asset name for the texture under the game's Content folder. Use \ (or \\ in JSON) to separate name segments if needed. For example, vanilla fruit trees use TileSheets\fruitTrees. | ||||||||||||
TextureSpriteRow | The tree's row index in the Texture spritesheet (e.g. 0 for the first tree, 1 for the second tree, etc). | ||||||||||||
PlantableLocationRules | (Optional) The rules to decide which locations you can plant the sapling in, if applicable. The first matching rule is used. This can override location checks (e.g. crops being limited to the farm), but not built-in requirements like crops needing dirt.
This consists of a list of models with these fields:
| ||||||||||||
CustomFields | The custom fields for this entry. |
For example, this content pack adds a custom fruit tree, including custom items for the sapling and fruit:
{
"Format": "2.3.0",
"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
},
]
}
The fruit trees can then be added to the game by giving the player a sapling item in the usual ways (e.g. from a shop).
Fruit items
For C# mods, the fruitsOnTree field (number of fruit on the tree) has been replaced by fruit (list of fruit items).
Spawning fruit trees
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).