ItemStorageAsset — Storage Barricade Definition
Overview
ItemStorageAsset extends ItemBarricadeAsset with an inventory grid system. It defines storage containers: crates, lockers, chests, wardrobes, fridges, and display cases. The class adds inventory grid dimensions, display case mode, auto-close behavior, player-open toggles, delete-on-destroy behavior, and pre-populated default contents.
Storage barricades inherit the full ItemBarricadeAsset property set (health, range, placement, explosion, build type, locking, etc.) and add inventory-specific fields. The build type for storage is typically EBuild.STORAGE or EBuild.STORAGE_WALL.
ItemSentryAsset inherits from ItemStorageAsset because sentries use their inventory grid to store ammunition and a weapon.
Source code location: Unturned/Bundles/ItemStorageAsset.cs (149 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, explosion
└─ ItemStorageAsset — inventory grid, display, default contents
└─ ItemSentryAsset — sentry turret (uses storage for ammo)Class Definition
csharp
public class ItemStorageAsset : ItemBarricadeAsset
{
protected byte _storage_x;
protected byte _storage_y;
protected bool _isDisplay;
public byte storage_x => _storage_x;
public byte storage_y => _storage_y;
public bool isDisplay => _isDisplay;
public bool shouldCloseWhenOutsideRange { get; protected set; }
public bool CanPlayersOpen { get; set; }
public bool ShouldDeleteContainedItemsOnDestroy { get; set; }
public LevelAsset.DefaultLoadoutItem[] DefaultContainedItems { get; set; }
public void AddDefaultContainedItemsToStorage(InteractableStorage storage) { ... }
public override byte[] getState(EItemOrigin origin) { ... }
}Inventory Grid Dimensions
| Field | .dat Key | Type | Default | Range | Notes |
|---|---|---|---|---|---|
_storage_x | Storage_X | byte | 1 (clamped) | 1–255 | Grid width (columns) |
_storage_y | Storage_Y | byte | 1 (clamped) | 1–255 | Grid height (rows) |
Parsing with Minimum
csharp
_storage_x = p.data.ParseUInt8("Storage_X");
if (storage_x < 1)
_storage_x = 1;
_storage_y = p.data.ParseUInt8("Storage_Y");
if (storage_y < 1)
_storage_y = 1;The minimum enforced value is 1 in each dimension. A storage of 1 × 1 provides a single item slot. Values of 0 are clamped to 1 — storage is never fully disabled.
Description Display
csharp
if (storage_x > 0 && storage_y > 0)
{
builder.Append(localization.format("ItemDescription_StorageDimensions",
storage_x, storage_y), DescSort_Important);
}Display format: Storage: 5 × 6
Common Storage Sizes
| Size | Slots | Typical Item |
|---|---|---|
| 1×1 | 1 | Small ammo box |
| 3×3 | 9 | Wooden crate |
| 5×4 | 20 | Metal locker |
| 5×6 | 30 | Wardrobe |
| 7×7 | 49 | Large industrial crate |
Note: ItemBagAsset (clothing storage) uses Width/Height keys. ItemStorageAsset uses Storage_X/Storage_Y. These are different keys for different storage systems.
Display Case Mode
csharp
_isDisplay = p.data.ContainsKey("Display");| .dat Key | Type | Default | Effect |
|---|---|---|---|
Display | flag | — | Storage acts as a display case |
State Difference
Display cases have a larger state array:
csharp
public override byte[] getState(EItemOrigin origin)
{
if (isDisplay)
return new byte[21];
else
return new byte[17];
}| Mode | State size | Extra bytes |
|---|---|---|
| Standard storage | 17 bytes | Owner (8) + Group (8) + Interact (1) |
| Display case | 21 bytes | +4 bytes for displayed item reference |
The additional 4 bytes store the item being displayed. This allows display cases to show a specific item model to other players without exposing the full inventory.
Should Close When Outside Range
csharp
shouldCloseWhenOutsideRange = p.data.ParseBool("Should_Close_When_Outside_Range", defaultValue: false);| .dat Key | Type | Default | Behavior |
|---|---|---|---|
Should_Close_When_Outside_Range | bool | false | Auto-close storage UI when player moves away |
When true, the storage interface automatically closes when the player moves beyond the interaction range. This is a UX convenience feature — it prevents the storage UI from staying open when the player walks away, which would block mouse input for non-storage interactions.
Can Players Open
csharp
CanPlayersOpen = p.data.ParseBool("Can_Players_Open", true);| .dat Key | Type | Default | Behavior |
|---|---|---|---|
Can_Players_Open | bool | true | Whether players can interact to open storage |
When false, the storage cannot be opened by players. This is useful for:
- Pre-placed sentry ammo storage (prevents players from stealing sentry guns)
- Decorative storage that shouldn't be interactive
- Storage that is opened through script/event rather than player interaction
Should Delete Contained Items On Destroy
csharp
ShouldDeleteContainedItemsOnDestroy = p.data.ParseBool("Delete_Contained_Items_On_Destroy");| .dat Key | Type | Default | Behavior |
|---|---|---|---|
Delete_Contained_Items_On_Destroy | bool | false | Items are deleted instead of dropped when destroyed |
When true, destroying the storage container permanently deletes all contained items rather than dropping them on the ground. This is useful for:
- Sentry ammo boxes (ammo should not be lootable by destroying the sentry)
- Temporary/event storage that shouldn't spill items
- Safety: prevents item duplication exploits
When false (default), items drop at the destruction point with the standard ±2m scatter pattern.
Default Contained Items
csharp
if (p.data.TryGetList("Default_Contained_Items", out IDatList itemsNode))
{
DefaultContainedItems = itemsNode.ParseArrayOfStructs<LevelAsset.DefaultLoadoutItem>();
}| .dat Key | Type | Purpose |
|---|---|---|
Default_Contained_Items | Array of DefaultLoadoutItem | Items spawned in storage on first placement |
Pre-Population Logic
csharp
public void AddDefaultContainedItemsToStorage(InteractableStorage storage)
{
if (storage == null || DefaultContainedItems.IsNullOrEmpty())
return;
foreach (LevelAsset.DefaultLoadoutItem item in DefaultContainedItems)
{
ItemAsset itemAsset = item.ResolveAsset(OnGetDefaultContainedItemsErrorContext);
if (itemAsset == null)
continue;
for (int amount = 0; amount < item.amount; ++amount)
{
storage.items.tryAddItem(new Item(itemAsset, item.origin), false);
}
}
storage.items.onStateUpdated?.Invoke();
}When a storage barricade is placed for the first time (not loaded from save), AddDefaultContainedItemsToStorage populates the storage with items defined in Default_Contained_Items. Each item specifies:
- Asset reference (GUID)
- Amount (quantity)
- Origin (crafted, nature, admin, etc.)
The onStateUpdated callback is invoked after all items are added to notify listeners.
BuildDescription — Inventory Tooltip
csharp
public override void BuildDescription(ItemDescriptionBuilder builder, Item itemInstance)
{
base.BuildDescription(builder, itemInstance);
if (storage_x > 0 && storage_y > 0)
{
builder.Append(localization.format("ItemDescription_StorageDimensions",
storage_x, storage_y), DescSort_Important);
}
}The storage dimensions are appended to the barricade description (health, armor tier, etc.) with DescSort_Important priority.
BuildCargoData — Wiki Export
csharp
CargoDeclaration data = builder.GetOrAddDeclaration("Storage");
data.Append("GUID", GUID);
data.Append("Storage_X", storage_x);
data.Append("Storage_Y", storage_y);
data.Append("Display", isDisplay);
data.Append("Should_Close_When_Outside_Range", shouldCloseWhenOutsideRange);| Column | Source |
|---|---|
GUID | PK, FK to Barricade table |
Storage_X | _storage_x |
Storage_Y | _storage_y |
Display | _isDisplay |
Should_Close_When_Outside_Range | shouldCloseWhenOutsideRange |
.dat File Reference — Storage-Specific
| .dat Key | Type | Default | Notes |
|---|---|---|---|
Storage_X | byte | 1 (clamped) | Grid columns |
Storage_Y | byte | 1 (clamped) | Grid rows |
Display | flag | — | Enable display case mode |
Should_Close_When_Outside_Range | bool | false | Auto-close on move |
Can_Players_Open | bool | true | Allow player interaction |
Delete_Contained_Items_On_Destroy | bool | false | Delete items on destroy |
Default_Contained_Items | array | — | Pre-populate items on first placement |
All ItemBarricadeAsset and ItemPlaceableAsset keys are also available.
Modding Example — Wooden Crate .dat
ini
GUID a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
Type Barricade
Build Storage
Health 200
Range 4
Radius 0.5
Offset 0.1
Storage_X 5
Storage_Y 4
Armor_Tier LowCreates a 5×4 (20-slot) wooden crate with 200 HP.
Modding Example — Display Case .dat
ini
GUID f1e2d3c4b5a69788796a5b4c3d2e1f0a
Type Barricade
Build Storage
Health 100
Range 4
Radius 0.3
Offset 0.1
Storage_X 3
Storage_Y 2
Display
Armor_Tier LowCreates a 3×2 display case (21-byte state) that shows a displayed item model.
Modding Example — Pre-Populated Locker .dat
ini
GUID d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9
Type Barricade
Build Storage
Health 400
Range 4
Radius 0.5
Offset 0.1
Storage_X 5
Storage_Y 6
Armor_Tier High
Default_Contained_Items
[
{ "GUID": "abc...", "Amount": 2, "Origin": "Craft" },
{ "GUID": "def...", "Amount": 1, "Origin": "Nature" }
]Creates a high-armor locker that spawns with 2 crafted items and 1 natural item on first placement.
Common Issues
Storage_X vs Width:
ItemStorageAssetusesStorage_X/Storage_Y.ItemBagAsset(clothing storage) usesWidth/Height. These are completely separate systems with different key names.Zero dimensions clamped: Setting
Storage_X 0is automatically clamped to1. There is no way to create a storage barricade with zero inventory slots.Display case state size: Display cases have a 21-byte state vs 17-byte standard. This is automatically handled by
getStatebased on theDisplayflag.Default contained items origin: The
DefaultLoadoutItem.originfield determines the item's origin. This affects stack merging and some game mechanics that check item origin.Delete-on-destroy safety: When
Delete_Contained_Items_On_Destroyisfalse, all items physically drop at the destruction point. With large inventories, this can cause performance issues from many dropped item entities.
Document history
| Version | Date | Author | Notes |
|---|---|---|---|
| 1.0 | 2026-07-28 | 57 Studios | Initial publication. Full storage asset documentation including grid dimensions, display case, default contents, and modding examples. |
