Material sources¶
A material source is the framework’s answer to “how does a piece get paid for?” It’s a small pluggable interface, so the builder doesn’t care whether materials come from a player’s backpack, a single build-kit container, a bag of color-coded packs, or something you invent.
The interface¶
A material source is any object implementing:
source:canConsume(req) -> boolean -- can we afford this requirement right now?
source:consume(req) -> boolean -- consume it (called per piece during build)
source:refund(req) -> boolean -- give it back (disassembly)
source:availableSummary() -> table -- for the UI's material readout
source:describe() -> string
req is a piece’s materialRequirement ({ fullType?, tag?, count }). The builder calls
canConsume/consume once per piece; if any consume fails mid-build, the whole build rolls
back and already-consumed materials are refunded.
The three built-in kinds¶
You pick one with def.materialSource:
Kind |
Model |
|---|---|
|
Consume straight from the player’s inventory, item by item. The default, everyday choice - “you need 2 planks per wall, take them from your bag.” |
|
One container item holds per-piece counts (a “build kit” you fill once). Good for a self-contained deployable. |
|
A bag of variant containers - e.g. a tent pack per color, each holding that variant’s pieces. Used by MilitaryTents. |
The framework registers these factories under those names; MaterialSource.fromDef(...)
resolves the right one from your def.
Custom sources¶
For anything else, set def.createMaterialSource(character, container, plan) and return your
own object implementing the interface. It wins over materialSource. Example uses: pulling
from a base’s connected stockpile, spending a currency, or a creative-mode “free” source that
always returns true.
Recipes vs. requirements¶
A materialRequirement is one item type. When a piece costs several different things -
and some are tools you keep - use a materialRecipe and the
RecipeSource, which validates and consumes the whole
recipe atomically:
materialRecipe = {
{ fullType = "Base.Plank", count = 4 },
{ fullType = "Base.Nails", count = 8 },
{ tag = "Hammer", count = 1, keep = true }, -- present but not consumed
}
RecipeSource is standalone (Tier-1 vendorable) - you can use it for any “do I have all these
ingredients?” check, framework or not.
See also
How-to → Materials & unlocks for the practical recipes.