ItemTankAsset — Storage Tank Items
ItemTankAsset defines placeable storage tanks — barricades that hold a single resource type (fuel or water). It extends ItemBarricadeAsset, inheriting the full barricade placement and health system while adding a 2-byte resource state and source type discrimination. At 73 lines it is a compact, focused asset class.
Source code location: Unturned/Bundles/ItemTankAsset.cs
Inheritance Chain
ItemAsset
→ ItemBarricadeAsset
→ ItemTankAssetExtending ItemBarricadeAsset gives tanks the full barricade pipeline: placement validation, health, salvage, build requirements, and collision detection. The tank adds resource storage on top of that foundation.
Class Definition
csharp
public class ItemTankAsset : ItemBarricadeAsset
{
protected ETankSource _source;
public ETankSource source => _source;
protected ushort _resource;
public ushort resource => _resource;
private byte[] resourceState;
}Core Fields
| Field | Type | .dat Key | Description |
|---|---|---|---|
_source | ETankSource | Source | Resource type: FUEL or WATER |
_resource | ushort | Resource | Maximum storage capacity (0-65,535) |
ETankSource Enum
csharp
public enum ETankSource { FUEL, WATER }The source type determines:
- HUD label: "Fuel Capacity" vs "Water Capacity".
- Interaction system: Fuel tanks connect to the vehicle fuel system; water tanks connect to the water collection system.
- UI icon: Different icons for fuel vs water containers.
- Transfer sound: Different audio effects for filling/emptying fuel vs water.
State Management
csharp
private byte[] resourceState;
public override byte[] getState(EItemOrigin origin)
{
byte[] state = new byte[2];
if (origin == EItemOrigin.ADMIN)
{
state[0] = resourceState[0];
state[1] = resourceState[1];
}
return state;
}| Origin | Initial State |
|---|---|
ADMIN | Full (_resource bytes) |
| All others | 0 (empty) |
| Loaded from save | Saved value restored by barricade system |
The 2-byte state is identical in format to ItemFuelAsset — a ushort resource amount. The resourceState cache is built during PopulateAsset:
csharp
_resource = p.data.ParseUInt16("Resource");
resourceState = BitConverter.GetBytes(resource);PopulateAsset
csharp
public override void PopulateAsset(in PopulateAssetParameters p)
{
base.PopulateAsset(in p);
_source = (ETankSource)Enum.Parse(typeof(ETankSource),
p.data.GetString("Source"), true);
_resource = p.data.ParseUInt16("Resource");
resourceState = BitConverter.GetBytes(resource);
}The Source key uses case-insensitive Enum.Parse with true for ignoreCase. Valid values: "FUEL" and "WATER".
BuildDescription
csharp
public override void BuildDescription(ItemDescriptionBuilder builder, Item itemInstance)
{
base.BuildDescription(builder, itemInstance);
switch (source)
{
case ETankSource.FUEL:
builder.Append(localization.format("ItemDescription_FuelCapacity", resource),
DescSort_Important);
break;
case ETankSource.WATER:
builder.Append(localization.format("ItemDescription_WaterCapacity", resource),
DescSort_Important);
break;
}
}The description shows the resource type and maximum capacity. The base class appends standard barricade information (health, placement restrictions).
InteractableTank Runtime Behavior
The tank's runtime behavior is provided by InteractableTank (not ItemTankAsset itself). The interactable system supports:
Fill and Drain Operations
- Fill from container: Player holds a fuel can or water bottle. Right-click on the tank transfers resource.
- Drain to container: Player holds an empty fuel can or water bottle. Resource transfers from tank to container.
- Network synchronization: Resource amount is synced to all clients near the tank.
- State save: Resource amount persists in the barricade save data.
Source-Specific Behavior
| Source | Compatible Items | Fill Source |
|---|---|---|
FUEL | ItemFuelAsset cans | Vehicles with fuel, generators |
WATER | ItemRefillAsset containers, ItemWaterAsset bottles | Rain, water purifiers |
Water Tank Special Features
Water tanks of type WATER connect to the rain collection and water purification systems:
- Rain fills water tanks placed outdoors.
- Water purifiers can fill water tanks placed nearby.
- Players can extract clean water from tanks using canteens and bottles.
- Tanks act as intermediate storage between water sources and portable containers.
Comparison to ItemFuelAsset
| Feature | ItemFuelAsset | ItemTankAsset |
|---|---|---|
| Base class | ItemAsset | ItemBarricadeAsset |
| Is placeable | No | Yes |
| Has health | No (stackable item) | Yes (barricade health) |
| Resource type | Fuel only | Fuel or Water |
| Fill from target | Yes (reverse transfer) | No |
| State lifetime | Item lifetime | Until barricade destruction |
| Bundle dependencies | "Use" AudioClip | Barricade prefab |
Cargo Data Export
csharp
CargoDeclaration data = builder.GetOrAddDeclaration("Tank");
data.Append("GUID", GUID);
data.Append("Source", source);
data.Append("Resource", resource);The base class appends barricade fields from ItemBarricadeAsset.BuildCargoData.
Common Issues
- Source immutability — The source type (
FUELorWATER) is part of the asset, not the state. A placed fuel tank cannot be converted to water storage after placement. The player must craft and place a different tank asset. - Empty on spawn — Non-admin spawns always start empty. A tank placed in the world by a player starts with 0 resource regardless of the
Resourcecapacity value in the asset. - Resource capacity validation — The
_resourcevalue is aushort(max 65,535) butInteractableTankmay have practical limits based on transfer rates and UI display. Very large capacity values may cause transfer performance issues. - Water source detection — Water tanks don't auto-detect nearby purification sources. The fill process requires player interaction (pump or manual refill). Rain collection is the only passive fill mechanism.
- Fuel tank placement rules — As a barricade, fuel tanks are subject to barricade placement rules. Safezone restrictions and building permissions apply. A fuel tank placed in a safezone that blocks building will fail.
