ItemFarmAsset — Farm Barricade Definition
Overview
ItemFarmAsset extends ItemBarricadeAsset with crop growth and harvesting mechanics. It defines plantable barricades that go through growth stages (seedling → growing → mature → ready), can be harvested for items, and are affected by rain, fertilizer, and the Agriculture player skill. The class supports both legacy item IDs and modern spawn tables for harvest rewards.
Farm barricades use EBuild.FARM with a 4-byte state storing the Unix timestamp of when the crop was planted. Growth progress is calculated as elapsed time divided by the Growth duration. Visual states transition at 33% and 66% progress thresholds.
Source code location: Unturned/Bundles/ItemFarmAsset.cs (150 lines), inheriting from ItemBarricadeAsset.cs (605 lines), ItemPlaceableAsset.cs (454 lines), and ItemAsset.cs (base).
Inheritance Chain
ItemAsset → IArmorFalloff
└─ ItemPlaceableAsset — salvage, destroy drops, crafting tags, armor falloff
└─ ItemBarricadeAsset — EBuild system, placement, health
└─ ItemFarmAsset — growth, harvest, skill integrationClass Definition
csharp
public class ItemFarmAsset : ItemBarricadeAsset
{
protected uint _growth;
protected ushort _grow;
public System.Guid growSpawnTableGuid;
public uint growth => _growth;
public ushort grow => _grow;
public bool ignoreSoilRestrictions { get; protected set; }
public bool canFertilize { get; protected set; }
public uint harvestRewardExperience;
public bool isAffectedByAgricultureSkill { get; protected set; }
public bool shouldRainAffectGrowth { get; protected set; }
internal NPCRewardsList harvestRewardsList;
public override void BuildDescription(ItemDescriptionBuilder builder, Item itemInstance) { ... }
public override void PopulateAsset(in PopulateAssetParameters p) { ... }
internal override void BuildCargoData(CargoBuilder builder) { ... }
}Growth System
Growth Duration
| .dat Key | Type | Default | Unit |
|---|---|---|---|
Growth | uint | Required | Seconds for full growth |
csharp
_growth = p.data.ParseUInt32("Growth");The growth duration in seconds. A value of 600 means the crop takes 10 minutes to fully grow. No default — the key is required for the farm to function.
Growth Calculation
csharp
uint plantedTime = BitConverter.ToUInt32(instance.state, 0);
uint currentTime = Provider.time;
uint elapsedSeconds = currentTime - plantedTime;
float growthPercent = Mathf.Clamp01((float)elapsedSeconds / growth);The 4-byte FARM state stores Provider.time at planting. Growth progress is the ratio of elapsed time to total growth duration.
Growth Stages
| Progress | Visual State | Interaction |
|---|---|---|
| 0–33% | Seedling | Cannot harvest |
| 33–66% | Growing | Cannot harvest |
| 66–99% | Mature | Cannot harvest |
| 100% | Ready | Can harvest |
The visual state transitions are handled by the interactable farm system based on growthPercent thresholds.
Harvest System
Legacy Grow ID
| .dat Key | Type | Purpose |
|---|---|---|
Grow | ushort | Legacy item ID of harvest result |
csharp
_grow = p.data.ParseUInt16("Grow");The legacy harvest item ID. This is the older system — Grow_SpawnTable takes priority if both are set.
Grow Spawn Table
| .dat Key | Type | Purpose |
|---|---|---|
Grow_SpawnTable | GUID | Spawn table for harvest result |
csharp
growSpawnTableGuid = p.data.ParseGuid("Grow_SpawnTable");The modern harvest system uses a spawn table GUID. When set, the farm resolves a random item from the spawn table on harvest. This enables loot-table-style farming where different items can drop from the same crop.
Priority
If Grow_SpawnTable is set, it takes priority over the legacy Grow ID. If neither is set, the farm produces nothing on harvest.
Description Display
csharp
if (grow != 0)
{
ItemAsset growAsset = Assets.find(EAssetType.ITEM, grow) as ItemAsset;
if (growAsset != null)
{
builder.Append(localization.format("ItemDescription_Farmable_GrowSpecificItem",
"<color=" + Palette.hex(ItemTool.getRarityColorUI(growAsset.rarity)) + ">"
+ growAsset.itemName + "</color>"), DescSort_Important);
}
}The legacy harvest item is shown in the tooltip with its rarity-colored name. Spawn table harvests are not displayed in the tooltip — only the legacy Grow ID triggers a tooltip line.
Rain Growth Acceleration
csharp
shouldRainAffectGrowth = p.data.ParseBool("Rain_Affects_Growth", defaultValue: true);| .dat Key | Type | Default | Effect |
|---|---|---|---|
Rain_Affects_Growth | bool | true | Rain speeds up crop growth |
When raining, the effective growth time is reduced: growth /= 1 + rainIntensity. Heavier rain causes faster growth. This simulates real-world farming where rainwater accelerates plant growth.
When false, rain has no effect — the crop grows at the base rate regardless of weather.
Agriculture Skill Integration
csharp
isAffectedByAgricultureSkill = p.data.ParseBool("Affected_By_Agriculture_Skill", defaultValue: true);| .dat Key | Type | Default | Effect |
|---|---|---|---|
Affected_By_Agriculture_Skill | bool | true | Agriculture skill provides bonus |
When true, the player's Agriculture skill level reduces growth time: growth *= (1 - skillLevel * config.reductionPerLevel). Higher skill = faster growth. The skill also provides a chance for a second harvest item.
When false, the Agriculture skill has no effect.
Fertilizer Support
csharp
canFertilize = p.data.ParseBool("Allow_Fertilizer", defaultValue: true);| .dat Key | Type | Default | Effect |
|---|---|---|---|
Allow_Fertilizer | bool | true | Fertilizer items can be applied |
When true, players can use fertilizer items on the farm to accelerate growth. When false, fertilizer cannot be applied.
Soil Restrictions
csharp
ignoreSoilRestrictions = p.data.ContainsKey("Ignore_Soil_Restrictions");| .dat Key | Type | Default | Effect |
|---|---|---|---|
Ignore_Soil_Restrictions | flag | — | Bypasses soil requirement |
By default, farms require soil (plantable terrain). Setting Ignore_Soil_Restrictions allows planting on any surface. This is common in modded farms that use planters, hydroponics, or grow-beds that provide their own growing medium.
Tooltip note: The description only shows the "Requires Soil" line when ignoreSoilRestrictions is false — the restriction is shown rather than the bypass, as requiring soil is the vanilla default.
Harvest Reward Experience
csharp
harvestRewardExperience = p.data.ParseUInt32("Harvest_Reward_Experience", defaultValue: 1);| .dat Key | Type | Default | Effect |
|---|---|---|---|
Harvest_Reward_Experience | uint | 1 | XP granted on successful harvest |
Harvest Rewards (NPC Quest System)
csharp
harvestRewardsList.Parse(p.data, p.localization, this, "Harvest_Rewards", "Harvest_Reward_");Farms can grant NPC-style rewards when harvested. This internal system allows quest-like reward triggers on crop harvest. The reward list is parsed from the .dat using the same infrastructure as NPC quest rewards.
BuildDescription — Inventory Tooltip
csharp
public override void BuildDescription(ItemDescriptionBuilder builder, Item itemInstance)
{
base.BuildDescription(builder, itemInstance);
if (grow != 0) { /* show harvest item with rarity color */ }
builder.stringBuilder.Clear();
if (!ignoreSoilRestrictions)
builder.stringBuilder.Append("Requires Soil");
if (canFertilize)
{
if (builder.stringBuilder.Length > 0) builder.stringBuilder.Append(' ');
builder.stringBuilder.Append("Can be Fertilized");
}
if (isAffectedByAgricultureSkill)
{
if (builder.stringBuilder.Length > 0) builder.stringBuilder.Append(' ');
builder.stringBuilder.Append("Affected by Agriculture Skill");
}
if (shouldRainAffectGrowth)
{
if (builder.stringBuilder.Length > 0) builder.stringBuilder.Append(' ');
builder.stringBuilder.Append("Affected by Rain");
}
if (builder.stringBuilder.Length > 0)
builder.Append(builder.stringBuilder.ToString(), DescSort_FarmableText);
}The description groups the soil/fertilizer/skill/rain flags into a single paragraph using string concatenation. This is a unique pattern — most other assets use separate builder lines.
BuildCargoData — Wiki Export
csharp
CargoDeclaration data = builder.GetOrAddDeclaration("Farm");
data.Append("GUID", GUID);
data.Append("Growth", growth);
data.Append("Grow", grow);
data.Append("Grow_SpawnTable", growSpawnTableGuid);
data.Append("Ignore_Soil_Restrictions", ignoreSoilRestrictions);
data.Append("Allow_Fertilizer", canFertilize);
data.Append("Harvest_Reward_Experience", harvestRewardExperience);
data.Append("Affected_By_Agriculture_Skill", isAffectedByAgricultureSkill);
data.Append("Rain_Affects_Growth", shouldRainAffectGrowth);.dat File Reference — Farm-Specific
| .dat Key | Type | Default | Notes |
|---|---|---|---|
Growth | uint | Required | Seconds for full growth |
Grow | ushort | — | Legacy harvest item ID |
Grow_SpawnTable | GUID | — | Spawn table for harvest (takes priority over Grow) |
Ignore_Soil_Restrictions | flag | — | No soil required |
Allow_Fertilizer | bool | true | Fertilizer accepted |
Harvest_Reward_Experience | uint | 1 | XP on harvest |
Affected_By_Agriculture_Skill | bool | true | Skill bonus applies |
Rain_Affects_Growth | bool | true | Rain accelerates growth |
Harvest_Rewards / Harvest_Reward_ | NPC rewards | — | NPC reward triggers on harvest |
Modding Example — Basic Tomato Plant .dat
ini
GUID a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
Type Barricade
Build Farm
Health 10
Range 4
Radius 0.3
Offset 0.05
Growth 600
Grow 12345
Harvest_Reward_Experience 510-minute growth, harvests item ID 12345, 5 XP per harvest.
Modding Example — Spawn Table Crop .dat
ini
GUID f1e2d3c4b5a69788796a5b4c3d2e1f0a
Type Barricade
Build Farm
Health 10
Range 4
Growth 300
Grow_SpawnTable abc-def-ghi-123
Allow_Fertilizer true5-minute growth, uses spawn table for random harvest (ignores legacy Grow), accepts fertilizer.
Modding Example — Hydroponic Planter .dat
ini
GUID d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9
Type Barricade
Build Farm
Health 50
Range 4
Growth 240
Grow 54321
Ignore_Soil_Restrictions
Affected_By_Agriculture_Skill false
Rain_Affects_Growth false4-minute growth, no soil required (self-contained planter), skill and rain disabled (controlled environment).
Common Issues
Farm produces nothing: Ensure either
Grow(legacy ID) orGrow_SpawnTable(GUID) is set. IfGrow_SpawnTableis set, it takes priority. If neither is set, harvest produces nothing.Growth too fast/slow:
Growthis in seconds. A common mistake is using minutes or ticks. 600 = 10 minutes. Use a calculator to verify.No growth progress: The farm state stores
Provider.timeat planting. If the farm was placed in a save file with a future timestamp, progress may never reach 100%.Soil restriction blocking placement: The default requires plantable terrain (soil). Use
Ignore_Soil_Restrictionsto bypass this for modded planters.Rain not affecting growth:
Rain_Affects_Growthdefaults totrue. If it's not working, verify the weather system is producing rain in the current map zone.
Document history
| Version | Date | Author | Notes |
|---|---|---|---|
| 1.0 | 2026-07-28 | 57 Studios | Initial publication. Full farm asset documentation including growth system, harvest mechanics, skill integration, and modding examples. |
