Containers
Version History
| Build Version | Change Date | Change Type | Description |
|---|---|---|---|
| 676042 | 2025-06-21 | stable | Current version |
Overview
The containers system manages all storage interfaces in Don't Starve Together, including backpacks, chests, cooking stations, and specialized containers. It defines UI layouts, item validation rules, and interaction behaviors for each container type.
The containers module provides:
- Widget Configuration: Slot positions, animations, and UI layout for container interfaces
- Item Validation: Rules determining which items can be placed in specific containers
- Interaction Behaviors: Button actions, sounds, and special container mechanics
- Container Types: Support for different container categories (pack, chest, cooker, hand_inv, side_inv_behind, top_rack)
Core Functions
containers.widgetsetup(container, prefab, data)
Sets up container widget configuration based on prefab or provided data.
Parameters:
container- The container component instanceprefab- Container prefab name (optional)data- Custom configuration data (optional)
Usage:
-- Called automatically during container initialization
containers.widgetsetup(self, "backpack")
-- Using custom data
local custom_config = {
widget = {
slotpos = {Vector3(0, 0, 0)},
animbank = "ui_chest_1x1",
animbuild = "ui_chest_1x1"
},
type = "chest"
}
containers.widgetsetup(self, nil, custom_config)
containers.MAXITEMSLOTS
Maximum number of item slots across all container types, calculated automatically during module initialization.
Container Configuration Structure
Each container configuration in params table contains:
Widget Properties
- slotpos: Array of Vector3 positions for inventory slots
- animbank/animbuild: Animation assets for container UI
- pos: Container widget position offset
- side_align_tip: Tooltip alignment for side containers
- buttoninfo: Configuration for action buttons (cooking, crafting, etc.)
- slotbg: Custom slot background images
- opensound/closesound: Audio cues for container interactions
Container Behavior
- type: Container category (
"pack","chest","cooker","hand_inv","side_inv_behind","top_rack","backpack") - acceptsstacks: Whether container accepts item stacks
- usespecificslotsforitems: Forces items to specific slot positions
- issidewidget: Renders container as side panel
- openlimit: Maximum concurrent users
- excludefromcrafting: Hides container contents from crafting recipes
- lowpriorityselection: Lower priority for automatic item selection
Item Validation
- itemtestfn: Function determining valid items for container
- priorityfn: Function for automatic item sorting priority
Container Types
Storage Containers
Backpacks
Prefabs: backpack, icepack, krampus_sack, piggyback, seedpouch, candybag, spicepack
-- Backpack configuration example (2x4 slots)
params.backpack = {
widget = {
slotpos = {}, -- 2x4 grid calculated in loop
animbank = "ui_backpack_2x4",
animbuild = "ui_backpack_2x4",
pos = Vector3(-5, -80, 0),
},
issidewidget = true,
type = "pack",
openlimit = 1,
}
-- Spice pack (2x3 slots)
params.spicepack = {
widget = {
slotpos = {}, -- 2x3 grid
animbank = "ui_icepack_2x3",
animbuild = "ui_icepack_2x3",
pos = Vector3(-5, -70, 0),
},
issidewidget = true,
type = "pack",
openlimit = 1,
}
Chests
Prefabs: treasurechest, icebox, chester, hutch, fish_box, boat_ancient_container, sacred_chest
-- Chester configuration (3x3 slots)
params.chester = {
widget = {
slotpos = {}, -- 3x3 grid calculated in loop
animbank = "ui_chest_3x3",
animbuild = "ui_chest_3x3",
pos = Vector3(0, 200, 0),
side_align_tip = 160,
},
type = "chest",
}
-- Icebox with food validation
function params.icebox.itemtestfn(container, item, slot)
if item:HasTag("icebox_valid") then
return true
end
-- Must be perishable
if not (item:HasTag("fresh") or item:HasTag("stale") or item:HasTag("spoiled")) then
return false
end
-- Must not be small creature
if item:HasTag("smallcreature") then
return false
end
-- Must be edible
for k, v in pairs(FOODTYPE) do
if item:HasTag("edible_"..v) then
return true
end
end
return false
end
Specialized Storage
Fish Box - Stores ocean creatures:
function params.fish_box.itemtestfn(container, item, slot)
return item:HasTag("smalloceancreature")
end
Salt Box - Preserves cookable foods:
function params.saltbox.itemtestfn(container, item, slot)
return ((item:HasTag("fresh") or item:HasTag("stale") or item:HasTag("spoiled"))
and item:HasTag("cookable")
and not item:HasTag("deployable")
and not item:HasTag("smallcreature")
and item.replica.health == nil)
or item:HasTag("saltbox_valid")
end
Cooking Containers
Cook Pot
Prefabs: cookpot, archive_cookpot, portablecookpot
-- Cook pot with cooking action
params.cookpot = {
widget = {
slotpos = {
Vector3(0, 64 + 32 + 8 + 4, 0),
Vector3(0, 32 + 4, 0),
Vector3(0, -(32 + 4), 0),
Vector3(0, -(64 + 32 + 8 + 4), 0),
},
buttoninfo = {
text = STRINGS.ACTIONS.COOK,
position = Vector3(0, -165, 0),
}
},
acceptsstacks = false,
type = "cooker",
}
function params.cookpot.itemtestfn(container, item, slot)
return cooking.IsCookingIngredient(item.prefab) and not container.inst:HasTag("burnt")
end
function params.cookpot.widget.buttoninfo.fn(inst, doer)
if inst.components.container ~= nil then
BufferedAction(doer, inst, ACTIONS.COOK):Do()
elseif inst.replica.container ~= nil and not inst.replica.container:IsBusy() then
SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.COOK.code, inst, ACTIONS.COOK.mod_name)
end
end
Portable Spicer
Prefab: portablespicer
-- Specific slot requirements for spicing
params.portablespicer = {
widget = {
slotpos = {
Vector3(0, 32 + 4, 0), -- Food slot
Vector3(0, -(32 + 4), 0), -- Spice slot
},
slotbg = {
{ image = "cook_slot_food.tex" },
{ image = "cook_slot_spice.tex" },
},
},
usespecificslotsforitems = true,
type = "cooker",
}
function params.portablespicer.itemtestfn(container, item, slot)
return item.prefab ~= "wetgoop"
and ( (slot == 1 and item:HasTag("preparedfood") and not item:HasTag("spicedfood")) or
(slot == 2 and item:HasTag("spice")) or
(slot == nil and (item:HasTag("spice") or (item:HasTag("preparedfood") and not item:HasTag("spicedfood"))))
)
and not container.inst:HasTag("burnt")
end
Character-Specific Containers
Wendy's Sisturn
function params.sisturn.itemtestfn(container, item, slot)
local owner
if TheWorld.ismastersim then
owner = container.inst.components.container:GetOpeners()[1]
elseif ThePlayer and container:IsOpenedBy(ThePlayer) then
owner = ThePlayer
end
-- Skill tree integration for expanded functionality
if not owner or (owner.components.skilltreeupdater and
owner.components.skilltreeupdater:IsActivated("wendy_sisturn_3")) then
return item.prefab == "petals" or item.prefab == "moon_tree_blossom" or item.prefab == "petals_evil"
end
return item.prefab == "petals"
end
Wortox's Soul Jar
function params.wortox_souljar.itemtestfn(container, item, slot)
return item:HasTag("soul") and not item:HasTag("nosouljar")
end
Beard Sacks (Webber's Beard)
Prefabs: beard_sack_1, beard_sack_2, beard_sack_3
-- Progressive storage capacity based on beard length
params.beard_sack_1 = {
widget = {
slotpos = { Vector3(0, 0, 0) },
slotbg = { { image = "inv_slot_morsel.tex" } },
animbank = "ui_beard_1x1",
animbuild = "ui_beard_1x1",
pos = Vector3(-82, 89, 0),
bottom_align_tip = -100,
},
type = "side_inv_behind",
acceptsstacks = true,
lowpriorityselection = true,
}
function params.beard_sack_1.itemtestfn(container, item, slot)
-- Accepts any edible items
for k, v in pairs(FOODGROUP.OMNI.types) do
if item:HasTag("edible_"..v) then
return true
end
end
end
Equipment Containers
Fishing Rod
Prefab: oceanfishingrod
-- Fishing tackle attachment
params.oceanfishingrod = {
widget = {
slotpos = {
Vector3(0, 32 + 4, 0), -- Bobber slot
Vector3(0, -(32 + 4), 0), -- Lure slot
},
slotbg = {
{ image = "fishing_slot_bobber.tex" },
{ image = "fishing_slot_lure.tex" },
},
},
usespecificslotsforitems = true,
type = "hand_inv",
excludefromcrafting = true,
}
function params.oceanfishingrod.itemtestfn(container, item, slot)
return (slot == nil and (item:HasTag("oceanfishing_bobber") or item:HasTag("oceanfishing_lure")))
or (slot == 1 and item:HasTag("oceanfishing_bobber"))
or (slot == 2 and item:HasTag("oceanfishing_lure"))
end
Slingshot Variants
Prefabs: slingshot, slingshotex, slingshot2, slingshot2ex, slingshot999ex
-- Ammunition container with skill requirements
function params.slingshot.itemtestfn(container, item, slot)
if item.REQUIRED_SKILL then
local owner
if TheWorld.ismastersim then
owner = container.inst.components.container:GetOpeners()[1]
elseif ThePlayer and container:IsOpenedBy(ThePlayer) then
owner = ThePlayer
end
if owner and not (owner.components.skilltreeupdater and
owner.components.skilltreeupdater:IsActivated(item.REQUIRED_SKILL)) then
return false
end
end
return item:HasTag("slingshotammo")
end
Slingshot Modification Container
Prefab: slingshotmodscontainer
params.slingshotmodscontainer = {
widget = {
slotpos = {
Vector3(220, 125, 0), -- Band slot
Vector3(20, -60, 0), -- Frame slot
Vector3(220, -150, 0), -- Handle slot
},
slotbg = {
{ image = "inv_slot_sketchy.tex", atlas = "images/hud2.xml" },
{ image = "inv_slot_sketchy.tex", atlas = "images/hud2.xml" },
{ image = "inv_slot_sketchy.tex", atlas = "images/hud2.xml" },
},
slotscale = 1.6,
slothighlightscale = 1.75,
},
usespecificslotsforitems = true,
acceptsstacks = false,
type = "cooker",
openlimit = 1,
}
function params.slingshotmodscontainer.itemtestfn(container, item, slot)
if slot == 1 then
return item:HasTag("slingshot_band")
elseif slot == 2 then
return item:HasTag("slingshot_frame")
elseif slot == 3 then
return item:HasTag("slingshot_handle")
elseif slot == nil then
return item:HasAnyTag("slingshot_band", "slingshot_frame", "slingshot_handle")
end
return false
end
Antlion Hat
Prefab: antlionhat
params.antlionhat = {
widget = {
slotpos = { Vector3(0, 2, 0) },
slotbg = { { image = "turf_slot.tex", atlas = "images/hud2.xml" } },
animbank = "ui_antlionhat_1x1",
animbuild = "ui_antlionhat_1x1",
pos = Vector3(106, 40, 0),
},
type = "hand_inv",
excludefromcrafting = true,
}
function params.antlionhat.itemtestfn(container, item, slot)
return item:HasTag("groundtile") and item.tile
end
Alter Guardian Hat
Prefabs: alterguardianhatshard, alterguardianhat
-- Shard version (1 slot)
function params.alterguardianhatshard.itemtestfn(container, item, slot)
return item:HasTag("spore")
end
-- Full version (5 slots)
local ALTERGUARDIANHAT_ITEMS = {"spore", "lunarseed"}
function params.alterguardianhat.itemtestfn(container, item, slot)
return item:HasAnyTag(ALTERGUARDIANHAT_ITEMS)
end
Specialized Containers
Bundle Wrapper
Prefab: bundle_container
-- Bundle creation interface
function params.bundle_container.itemtestfn(container, item, slot)
return not (item:HasTag("irreplaceable") or item:HasTag("_container") or
item:HasTag("bundle") or item:HasTag("nobundling"))
end
function params.bundle_container.widget.buttoninfo.validfn(inst)
return inst.replica.container ~= nil and not inst.replica.container:IsEmpty() and
not inst.replica.container:IsReadOnlyContainer()
end
Construction Containers
Prefabs: construction_container, construction_repair_container, construction_rebuild_container, enable_shadow_rift_construction_container, enable_lunar_rift_construction_container
-- Construction material interface
function params.construction_container.itemtestfn(container, item, slot)
local doer = container.inst.entity:GetParent()
return doer ~= nil
and doer.components.constructionbuilderuidata ~= nil
and doer.components.constructionbuilderuidata:GetIngredientForSlot(slot) == item.prefab
end
Woby Containers
Prefabs: wobysmall, wobybig, woby_rack_container
-- Woby rack for drying items
function params.woby_rack_container.itemtestfn(container, item, slot)
return item:HasTag("dryable")
or (TheWorld.ismastersim and (
item:GetTimeAlive() == 0 or -- Items perishing replaced by spoiled_food/fish
container.inst:GetTimeAlive() == 0 or -- Transferring items during woby transform
( item.wobyrack_lastinfo and -- Failing to move items; return to slot
item.wobyrack_lastinfo.container == container and
item.wobyrack_lastinfo.slot == slot
)
))
end
Offering Pots
Prefabs: offering_pot, offering_pot_upgraded
function params.offering_pot.itemtestfn(container, item, slot)
return not container.inst:HasTag("burnt") and item.prefab == "kelp"
end
Mushroom Lights
Prefabs: mushroom_light, mushroom_light2, yots_lantern_post
function params.mushroom_light.itemtestfn(container, item, slot)
return (item:HasTag("lightbattery") or item:HasTag("lightcontainer")) and not container.inst:HasTag("burnt")
end
-- Enhanced version accepts spores too
function params.mushroom_light2.itemtestfn(container, item, slot)
return (item:HasTag("lightbattery") or item:HasTag("spore") or item:HasTag("lightcontainer")) and not container.inst:HasTag("burnt")
end
Winter Tree Decorations
Prefabs: winter_tree, winter_twiggytree, winter_deciduoustree, winter_palmconetree
function params.winter_tree.itemtestfn(container, item, slot)
return item:HasTag("winter_ornament") and not container.inst:HasTag("burnt")
end
Merm Buildings
Prefabs: merm_toolshed, merm_toolshed_upgraded, merm_armory, merm_armory_upgraded
-- Tool shed (twigs and rocks)
function params.merm_toolshed.itemtestfn(container, item, slot)
return not container.inst:HasTag("burnt") and (
(slot == 1 and item.prefab == "twigs") or
(slot == 2 and item.prefab == "rocks") or
(slot == nil and (item.prefab == "twigs" or item.prefab == "rocks"))
)
end
-- Armory (logs and cut grass)
function params.merm_armory.itemtestfn(container, item, slot)
return not container.inst:HasTag("burnt") and (
(slot == 1 and item.prefab == "log") or
(slot == 2 and item.prefab == "cutgrass") or
(slot == nil and (item.prefab == "log" or item.prefab == "cutgrass"))
)
end
Pocket Watch
Prefab: pocketwatch
function params.pocketwatch.itemtestfn(container, item, slot)
return item:HasTag("pocketwatchpart")
end
Book Station
Prefab: bookstation
function params.bookstation.itemtestfn(container, item, slot)
return item:HasTag("bookcabinet_item")
end
Tackle Containers
Prefabs: tacklecontainer, supertacklecontainer
function params.tacklecontainer.itemtestfn(container, item, slot)
return item:HasTag("oceanfishing_bobber") or item:HasTag("oceanfishing_lure")
end
Halloween Tree
Prefab: livingtree_halloween
function params.livingtree_halloween.itemtestfn(container, item, slot)
return item:HasTag("halloween_ornament") and not container.inst:HasTag("burnt")
end
Dragonfly Furnace
Prefab: dragonflyfurnace
function params.dragonflyfurnace.itemtestfn(container, item, slot)
return not item:HasTag("irreplaceable")
end
function params.dragonflyfurnace.widget.buttoninfo.fn(inst, doer)
if inst.components.container ~= nil then
BufferedAction(doer, inst, ACTIONS.INCINERATE):Do()
elseif inst.replica.container ~= nil and not inst.replica.container:IsBusy() then
SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.INCINERATE.code, inst, ACTIONS.INCINERATE.mod_name)
end
end
Balatro Machine
Prefab: balatro_machine
params.balatro_machine = {
widget = {
slotpos = {
Vector3(0, 0, 0),
Vector3(68, 0, 0),
Vector3(68+68, 0, 0),
Vector3(68+68+68, 0, 0),
Vector3(68+68+68+68, 0, 0),
},
slotbg = {
{ image = "sisturn_slot_petals.tex" },
{ image = "sisturn_slot_petals.tex" },
{ image = "sisturn_slot_petals.tex" },
{ image = "sisturn_slot_petals.tex" },
{ image = "sisturn_slot_petals.tex" },
},
buttoninfo = {
text = STRINGS.ACTIONS.ACTIVATE.GENERIC,
position = Vector3(68+68, -68, 0),
},
},
acceptsstacks = false,
type = "cooker",
openlimit = 1,
}
function params.balatro_machine.itemtestfn(container, item, slot)
return not container.inst:HasTag("burnt")
end
function params.balatro_machine.widget.buttoninfo.fn(inst, doer)
if inst.components.container ~= nil then
BufferedAction(doer, inst, ACTIONS.ACTIVATE_CONTAINER):Do()
elseif inst.replica.container ~= nil and not inst.replica.container:IsBusy() then
SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.ACTIVATE_CONTAINER.code, inst, ACTIONS.ACTIVATE_CONTAINER.mod_name)
end
end
Webber's Beard Sacks
Prefabs: beard_sack_1, beard_sack_2, beard_sack_3
These containers represent Webber's growing beard functionality, providing increasing storage capacity:
-- Level 1 beard (1 slot)
params.beard_sack_1 = {
widget = {
slotpos = { Vector3(0, 0, 0) },
slotbg = { { image = "inv_slot_morsel.tex" } },
animbank = "ui_beard_1x1",
animbuild = "ui_beard_1x1",
pos = Vector3(-82, 89, 0),
bottom_align_tip = -100,
},
type = "side_inv_behind",
acceptsstacks = true,
lowpriorityselection = true,
}
-- Level 2 beard (2 slots)
params.beard_sack_2 = {
widget = {
slotpos = {
Vector3(-(64 + 12)/2, 0, 0),
Vector3( (64 + 12)/2, 0, 0),
},
slotbg = {
{ image = "inv_slot_morsel.tex" },
{ image = "inv_slot_morsel.tex" },
},
animbank = "ui_beard_2x1",
animbuild = "ui_beard_2x1",
pos = Vector3(-82, 89, 0),
bottom_align_tip = -100,
},
type = "side_inv_behind",
acceptsstacks = true,
lowpriorityselection = true,
}
-- Level 3 beard (3 slots)
params.beard_sack_3 = {
widget = {
slotpos = {
Vector3(-(64 + 12), 0, 0),
Vector3(0, 0, 0),
Vector3(64 + 12, 0, 0),
},
slotbg = {
{ image = "inv_slot_morsel.tex" },
{ image = "inv_slot_morsel.tex" },
{ image = "inv_slot_morsel.tex" },
},
animbank = "ui_beard_3x1",
animbuild = "ui_beard_3x1",
pos = Vector3(-82, 89, 0),
bottom_align_tip = -100,
},
type = "side_inv_behind",
acceptsstacks = true,
lowpriorityselection = true,
}
function params.beard_sack_1.itemtestfn(container, item, slot)
-- Accepts any edible items
for k, v in pairs(FOODGROUP.OMNI.types) do
if item:HasTag("edible_"..v) then
return true
end
end
end
-- Shared item test function for all beard levels
params.beard_sack_2.itemtestfn = params.beard_sack_1.itemtestfn
params.beard_sack_3.itemtestfn = params.beard_sack_1.itemtestfn
params.balatro_machine = {
widget = {
slotpos = {
Vector3(0, 0, 0),
Vector3(68, 0, 0),
Vector3(68+68, 0, 0),
Vector3(68+68+68, 0, 0),
Vector3(68+68+68+68, 0, 0),
},
buttoninfo = {
text = STRINGS.ACTIONS.ACTIVATE.GENERIC,
position = Vector3(68+68, -68, 0),
},
},
acceptsstacks = false,
type = "cooker",
openlimit = 1,
}
function params.balatro_machine.itemtestfn(container, item, slot)
return not container.inst:HasTag("burnt")
end
Additional Specialized Containers
Elixir Container (Wendy):
function params.elixir_container.itemtestfn(container, item, slot)
return item:HasTag("ghostlyelixir") or item:HasTag("ghostflower")
end
Battle Song Container:
function params.battlesong_container.itemtestfn(container, item, slot)
return item:HasTag("battlesong")
end
Bearger Fur Sack:
function params.beargerfur_sack.itemtestfn(container, item, slot)
return item:HasTag("beargerfur_sack_valid") or item:HasTag("preparedfood")
end
Houndstooth Blowpipe:
function params.houndstooth_blowpipe.itemtestfn(container, item, slot)
return item:HasTag("blowpipeammo")
end
Slingshot Ammo Container:
function params.slingshotammo_container.itemtestfn(container, item, slot)
return item:HasTag("slingshotammo")
end
Ocean Trawler:
function params.ocean_trawler.itemtestfn(container, item, slot)
return item:HasTag("cookable") or item:HasTag("oceanfish")
end
YOTb Sewing Machine:
function params.yotb_sewingmachine.itemtestfn(container, item, slot)
return item:HasTag("yotb_pattern_fragment")
end
Elixir Container (Wendy):
function params.elixir_container.itemtestfn(container, item, slot)
return item:HasTag("ghostlyelixir") or item:HasTag("ghostflower")
end
Battle Song Container:
function params.battlesong_container.itemtestfn(container, item, slot)
return item:HasTag("battlesong")
end
Bearger Fur Sack:
function params.beargerfur_sack.itemtestfn(container, item, slot)
return item:HasTag("beargerfur_sack_valid") or item:HasTag("preparedfood")
end
Houndstooth Blowpipe:
function params.houndstooth_blowpipe.itemtestfn(container, item, slot)
return item:HasTag("blowpipeammo")
end
Slingshot Ammo Container:
function params.slingshotammo_container.itemtestfn(container, item, slot)
return item:HasTag("slingshotammo")
end
Ocean Trawler:
function params.ocean_trawler.itemtestfn(container, item, slot)
return item:HasTag("cookable") or item:HasTag("oceanfish")
end
Teleportato Base (Legacy):
function params.teleportato_base.itemtestfn(container, item, slot)
return not item:HasTag("nonpotatable")
end
Shadow/Rabbit King Horn Containers:
function params.shadow_container.itemtestfn(container, item, slot)
return not item:HasTag("irreplaceable")
end
Event-Specific Containers (Quagmire)
These containers are used during the Quagmire event:
Quagmire Cooking Containers:
quagmire_pot,quagmire_pot_smallquagmire_casseroledish,quagmire_casseroledish_smallquagmire_grill,quagmire_grill_smallquagmire_pot_syrup
Quagmire Backpacks:
quagmire_backpack_small(4 slots)quagmire_backpack(8 slots)
function params.quagmire_pot.itemtestfn(container, item, slot)
return item:HasTag("quagmire_stewable")
and item.prefab ~= "quagmire_sap"
and ((item.components.inventoryitem ~= nil and not item.components.inventoryitem:IsHeld()) or
not (item.prefab == "spoiled_food" or item:HasTag("preparedfood") or item:HasTag("overcooked") or container.inst:HasTag("takeonly")))
end
function params.quagmire_pot_syrup.itemtestfn(container, item, slot)
return item:HasTag("quagmire_stewable")
and ((item.components.inventoryitem ~= nil and not item.components.inventoryitem:IsHeld()) or
(item.prefab == "quagmire_sap" and not container.inst:HasTag("takeonly")))
end
Advanced Features
Priority Systems
Specialized containers can implement priority functions for automatic item sorting:
-- Seed pouch prioritizes seeds
function params.seedpouch.itemtestfn(container, item, slot)
return item.prefab == "seeds" or string.match(item.prefab, "_seeds") or item:HasTag("treeseed")
end
params.seedpouch.priorityfn = params.seedpouch.itemtestfn
-- Candy bag prioritizes Halloween items
function params.candybag.itemtestfn(container, item, slot)
return item:HasTag("halloweencandy") or item:HasTag("halloween_ornament") or string.sub(item.prefab, 1, 8) == "trinket_"
end
params.candybag.priorityfn = params.candybag.itemtestfn
Deprecated Containers
Some containers are marked as deprecated but maintained for compatibility:
Shadow Chester - Used by Dragonfly Chest and Minotaur Chest:
--Deprecated; keep definition for dragonflychest, minotaurchest, mods,
--and also for legacy save data
params.shadowchester = {
widget = {
slotpos = {}, -- 3x4 grid
animbank = "ui_chester_shadow_3x4",
animbuild = "ui_chester_shadow_3x4",
pos = Vector3(0, 220, 0),
side_align_tip = 160,
},
type = "chest",
}
Integration Examples
Creating Custom Containers
-- Define new container configuration
params.my_custom_container = {
widget = {
slotpos = {
Vector3(-37.5, 32, 0),
Vector3(37.5, 32, 0),
Vector3(-37.5, -32, 0),
Vector3(37.5, -32, 0),
},
animbank = "ui_chest_2x2",
animbuild = "ui_chest_2x2",
pos = Vector3(200, 0, 0),
side_align_tip = 120,
},
type = "chest",
}
-- Add item validation
function params.my_custom_container.itemtestfn(container, item, slot)
return item:HasTag("my_custom_tag")
end
-- Apply to prefab
local function OnInit(inst)
containers.widgetsetup(inst.components.container, "my_custom_container")
end
Conditional Item Acceptance
-- Dynamic item testing based on container state
function params.conditional_container.itemtestfn(container, item, slot)
-- Check container upgrade level
if container.inst:HasTag("upgraded") then
return item:HasTag("advanced_material")
else
return item:HasTag("basic_material")
end
end
Complex Button Actions
-- Multi-stage button validation and execution
function params.complex_container.widget.buttoninfo.validfn(inst)
local container = inst.replica.container
if not container or container:IsEmpty() then
return false
end
-- Check for specific item combinations
local has_ingredient_a = container:Has("ingredient_a", 1)
local has_ingredient_b = container:Has("ingredient_b", 1)
return has_ingredient_a and has_ingredient_b
end
function params.complex_container.widget.buttoninfo.fn(inst, doer)
-- Custom action execution with confirmation dialog
if inst.components.container ~= nil then
BufferedAction(doer, inst, ACTIONS.CUSTOM_ACTION):Do()
elseif inst.replica.container ~= nil and not inst.replica.container:IsBusy() then
SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.CUSTOM_ACTION.code, inst, ACTIONS.CUSTOM_ACTION.mod_name)
end
end
Performance Considerations
The containers system calculates MAXITEMSLOTS automatically at module initialization:
for k, v in pairs(params) do
containers.MAXITEMSLOTS = math.max(containers.MAXITEMSLOTS, v.widget.slotpos ~= nil and #v.widget.slotpos or 0)
end
This ensures proper memory allocation for the largest possible container configuration.
Related Modules
- Components - Container component implementation
- Actions - Container interaction actions
- Recipes - Crafting integration with containers
- Networking - Container state synchronization
- Prefabs - Container prefab definitions
- Cooking - Cooking system integration
- Player - Player inventory interactions
Notes
🟢 Stable API: Container configuration structure is established and stable across updates.
⚠️ Performance: Large containers with complex itemtestfn can impact performance during item validation.
🔧 Modding: Custom containers can be added by extending the params table and ensuring proper widget setup.
📦 Memory: Container slot positions are pre-calculated during module load for optimal performance.
🎯 Skill Integration: Some containers check player skill tree progression for expanded functionality.
⭐ Event Containers: Quagmire containers are event-specific and may not be available in standard gameplay.